<:s><:#1200,9360>A PPL program is created by a programmer with a standard text editor. Each line consists of standard ASCII text (up to 2048 characters long) terminated with a carriage return/line feed pair. Character case is not significant except in literal text strings
. Three types of lines are recognized by the compiler: comment lines, variable declaration statements and code statements.
@Small_Header@<:s><:#259,9360>Comments
<:#1440,9360>Comments are used by the PPL programmer to make notes in the source code about what the code is supposed to do and generally clarify things so that code maintenance is easier. They are completely ignored by the PPL compiler so they may contain any text des
ired. A comment may be on a line all by itself or at the end of a line after a valid statement. A blank line is considered a comment. Any text following a quote character (') or semi-colon (;) is also a comment. The following are all valid comments:
@Example_Text@<:#948,9360>; This is a comment line<**>STRING buf, str, ssNum ' This is a comment too<**><**>' The blank line above this (as well as these<**>' lines) are all comments<**>CLS ; Yet *ANOTHER* comment!
<:s><:#2165,9360>Variable declaration statements must start with a keyword denoting the variable type. Valid type keywords are
<+!>BOOLEAN<-!>, <+!>DATE<-!>, <+!>INTEGER<-!>, <+!>MONEY<-!>, <+!>STRING<-!> and
<+!>TIME<-!>. The keyword must be followed by one or more valid variable names (or array declarations) which should be separated by commas (,). A valid variable name must start with a letter (A-Z) and may contain letters, numbers (0-9) and the underscore
character (_). Any number of characters may be used but only the first 32 will be recognized by PPL. If the variable is an array then the name should be followed by an open parenthesis <[>(], one, two or three constant subscript expressions (separated by
commas), and finally a closing parenthesis <[>)]. Here are some examples:
@Example_Text@<:#1106,9360><**>BOOLEAN adultFlag<**>DATE this_IS_a_VARIABLE_to_HOLD_todays_DATE<**>; Only this_IS_a_VARIALBE_to_HOLD_today is significant<**>INTEGER age<**>MONEY prices(2,5)<**>STRING buf, labels(10), ssNum<**>TIME start, stop
@Small_Header@<:s><:#259,9360>Code Statements
<:s><:#970,9360>Code declaration statements must start with a keyword indicating the operation or process to be performed. There is one exception to this rule, however, and that is the
<+!>LET<-!> statement. If no keyword is found at the beginning of a line, a
<+!>LET<-!> statement is implied and the rest of the line should follow the format:
@Example_Text@<:#158,9360>VAR = EXPRESSION
<:s><:#1440,9360>There are many statements defined in PPL and it is beyond the scope of this part of the manual to cover the precise syntax for each and every one of them. Simply put, a statement takes zero, one or more expressions (see Expressions later in this section) a
nd/or variable names (see Variable Declaration Statements) as arguments (separated by commas), does something, using any passed expressions and/or variables, and assigning new values, as needed, to passed variables. Here are a few sample statements:
@Example_Text@<:#2212,9360>' This statement clears the screen and takes no arguments<**>CLS<**><**>' Evaluates the single expression and assigns the result to ans<**>LET ans = 5+4*3/2-1<**><**>; Evaluates all three (could be more, could be less) expressions (two of<**>; which have on
ly one term) and prints them in order, following them<**>; with a carriage return<**>PRINTLN "The answer "+"is ",STRING(ans),"."<**><**>; Evaluate the expression on the left, display it, then get a string<**>; from the user and assign it to the variable nam
e on the left<**>INPUT "What is "+"your age",current_Age
Here are the valid statements accepted in PPL source code:<:A2>
<:#240,9360>
<:p<* >>
@Subhead@<:#360,9360>Expressions
<:s><:#1440,9360>An expression in PPL can take just about any form imaginable. It consists of one or more constants, variables (see Variable Declaration Statements), functions (which take zero, one or more arguments), or sub-expressions, all of which are separated by PPL o
perators. Although most statements and functions in PPL expect expressions of a specific type as arguments, you need not pass it an expression of the correct type; PPL will automatically convert from one type to another when it needs to. Here are a few sa
mple expressions:
@Example_Text@<:#2686,9360>' Define a few variables to hold expression results<**>INTEGER i, j, k<**>STRING s, t, u<**><**>' Single term expressions<**>' (All expressions here are to the right of the =)<**>LET i = 2<**>LET j = 3<**>LET k = 4<**>LET s = "STRING"<**><**>' Complex expre
ssions<**>LET i = i*j*k+2*i+3*j+k/2-5<**>LET j = i*j*(k+2)*(i+3)*(j+k)/(2-5)<**>LET k = (RANDOM(5)+1)*5+ABS(j)<**>LET t = CHR(i%256)<**>LET u = s+" "+t
<:s><:#240,9360>
@Small_Header@<:s><:#259,9360>Constants
<:s><:#480,9360>PPL supports both user defined constants and pre-defined constants. User defined constants may be any of the following:
@Indent_List@<:s><:#485,9360> $#.## A <+!>MONEY<-!> constant (dollar sign followed by optional dollars followed by decimal point followed by cents; # = 0-9)
@Indent_List@<:s><:#485,9360> ##h An <+!>INTEGER<-!> hexadecimal constant (a decimal digit followed by zero, one or more hexadecimal digits followed by an H; # = 0-9 & A-F)
@Indent_List@<:s><:#485,9360> ##d An <+!>INTEGER<-!> decimal constant (one or more decimal digits followed by a D; # = 0-9)
@Indent_List@<:s><:#485,9360> ##o An <+!>INTEGER<-!> octal constant (one or more octal digits followed by an O;<**># = 0-7)
@Indent_List@<:s><:#485,9360> ##b An <+!>INTEGER<-!> binary constant (one or more binary digits followed by a B;<**># = 0-1)
@Indent_List@<:s><:#485,9360> +/-## An <+!>INTEGER<-!> constant (an optional plus or minus sign followed by one or more decimal digits; # = 0-9)
@Indent_List@<:#485,9360> "X" A <+!>STRING<-!> constant (a double quote followed by displayable text followed by another double quote; X = any displayable text)
@Indent_List@<:s><:#485,9360> @X## An <+!>INTEGER<-!> @X constant (a commercial at sign followed by an X followed by two hexadecimal digits; # = 0-9 & A-F)
The following predefined constant labels are also available. Their values and uses will be defined later.<:N733529525,SDR,65535,1,1
Need to replace this with the name of a section later that will have the constants defined.
>
<:A9>
<:#240,9360>
@Small_Header@<:#259,9360>Functions
PPL supports many functions which may be used by the programmer in expressions. Here is a list of valid PPL functions. As with the predefined constants, their return values and uses will be documented later.<:N733529767,SDR,65535,2,1
Refer them to the list of functions later.
>
<:A8>
<:#240,9360>
@Small_Header@<:#259,9360>Sub-Expressions
<:s><:#480,9360>A sub-expression is simply any valid PPL expression surrounded by parentheses. For example, this is an expression:
@Example_Text@<:s><:#158,9360>7+6-5*4/3%2
<:s><:#240,9360>To make it into a sub-expression, surround it with parentheses like this:
@Example_Text@<:s><:#158,9360>(7+6-5*4/3%2)
<:s><:#240,9360>This sub-expression could be used in yet another expression:
<:s><:#240,9360>PPL supports a full set of operators in addition to the functions listed previously. They are:
@Indent_List@<:s><:#240,9360> Operator Function
@Indent_List@<:#480,9360> <:f,QCourier,>(<:f> Starts a sub-expression; requires a ) to terminate<**>Example:
<:f160,QCourier,>3*<+!>(<-!>2+1)<:f> (result is 9, not 7)
@Indent_List@<:#480,9360> <:f,QCourier,>)<:f> Ends a sub-expression<**>Example: <:f160,QCourier,>3*(2+1<+!>)<-!><:f> (result is 9, not 7)
@Indent_List@<:#725,9360> <:f,QCourier,>^<:f> Returns the result of raising a number to a specified power<**>Expects and returns type
<+!>INTEGER<-!><**>Example: <:f160,QCourier,>3<+!>^<-!>2<:f> (result is 9)
@Indent_List@<:#725,9360> <:f,QCourier,>*<:f> Returns the product of two numbers<**>Expects and returns type
<+!>INTEGER<-!><**>Example: <:f160,QCourier,>3<+!>*<-!>2<:f> (result is 6)
@Indent_List@<:#725,9360> <:f,QCourier,>/<:f> Returns the quotient of two numbers<**>Expects and returns type
<+!>INTEGER<-!><**>Example: <:f160,QCourier,>9<+!>/<-!>4<:f> (result is 2)
@Indent_List@<:#725,9360> <:f,QCourier,>%<:f> Returns the remainder of two numbers<**>Expects and returns type
<+!>INTEGER<-!><**>Example: <:f160,QCourier,>9<+!>%<-!>4<:f> (result is 1)
@Indent_List@<:#965,9360> <:f,QCourier,>+<:f> Returns the sum of two numbers or a string concatenated to another<**>Expects and returns type
<+!>INTEGER<-!> or <+!>STRING<-!><**>Example: <:f160,QCourier,>1<+!>+<-!>2<:f> (result is 3)<**>Example:
<:f160,QCourier,>"String plus "<+!>+<-!>"String"<:f> (result is "String plus String")
@Indent_List@<:#725,9360> <:f,QCourier,>-<:f> Returns the difference between two numbers<**>Expects and returns type
<+!>INTEGER<-!><**>Example: <:f160,QCourier,>3<+!>-<-!>2<:f> (result is 1)
@Indent_List@<:#980,9360> <:f,QCourier,>=<:f> Returns <+!>TRUE<-!> if two values are equal<**>Expects any type; returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,>3 <+!>=<-!> 3<:f> (result is
<+!>TRUE<-!>)<**>Example: <:f160,QCourier,>"String" <+!>=<-!> "STRING"<:f> (result is
<+!>FALSE<-!>)
@Indent_List@<:#980,9360> <:f,QCourier,><<<;><:f> Returns <+!>TRUE<-!> if two values are not equal<**>Expects any type; returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,>3 <:f160,QCourier,><+!><<<;><-!><:f160,QCourier,> 3<:f> (result is
<+!>FALSE<-!>)<**>Example: <:f160,QCourier,>"String" <+!><<<;><-!> "STRING"<:f> (result is
<+!>TRUE<-!>)
@Indent_List@<:#980,9360> <:f,QCourier,><<<:f> Returns <+!>TRUE<-!> if a value is less than another<**>Expects any type; returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,>2 <+!><<<-!> 3<:f> (result is
<+!>TRUE<-!>)<**>Example: <:f160,QCourier,>"STRING" <+!><<<-!> "STRING"<:f> (result is
<+!>FALSE<-!>)
@Indent_List@<:#980,9360> <:f,QCourier,><<=<:f> Returns <+!>TRUE<-!> if a value is less than or equal to another<**>Expects any type; returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,>2 <+!><<=<-!> 3<:f> (result is
<+!>TRUE<-!>)<**>Example: <:f160,QCourier,>"STRING" <+!><<=<-!> "STRING"<:f> (result is
<+!>TRUE<-!>)
@Indent_List@<:#980,9360> <:f,QCourier,><;><:f> Returns <+!>TRUE<-!> if a value is greater than another<**>Expects any type; returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,>2 <+!><;><-!> 3<:f> (result is
<+!>FALSE<-!>)<**>Example: <:f160,QCourier,>"STRING" <+!><;><-!> "STRING"<:f> (result is
<+!>FALSE<-!>)
@Indent_List@<:#980,9360> <:f,QCourier,><;>=<:f> Returns <+!>TRUE<-!> if a value is greater than or equal to another<**>Expects any type; returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,>2 <+!><;>=<-!> 3<:f> (result is
<+!>FALSE<-!>)<**>Example: <:f160,QCourier,>"STRING" <+!><;>=<-!> "STRING"<:f> (result is
<+!>TRUE<-!>)
@Indent_List@<:#735,9360> <:f,QCourier,>!<:f> Returns the logical not of a <+!>BOOLEAN<-!> value<**>Expects and returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,><+!>!<-!>TRUE<:f> (result is
<+!>FALSE<-!>)
@Indent_List@<:#735,9360> <:f,QCourier,>&<:f> Returns the logical and of two <+!>BOOLEAN<-!> values<**>Expects and returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,>TRUE <+!>&<-!> FALSE<:f> (result is
<+!>FALSE<-!>)
@Indent_List@<+@><:#735,9360> <:f,QCourier,>|<:f> Returns the logical or of two <+!>BOOLEAN<-!> values<**>Expects and returns type
<+!>BOOLEAN<-!><**>Example: <:f160,QCourier,>TRUE <+!>|<-!> FALSE<:f> (result is
<+!>TRUE<-!>)
<:#480,9360>PPL operators have a precedence between one and six that determines which operators get processed first. A precedence of one gets processed first, six gets processed last.
<:#480,9360>Binary operators expect both the left and right operands to be of the same type. If they are not then appropriate type conversions will be performed automatically.
@Indent_List@<:s><:p<* >>
@Title@<:s><:#482,9360>PPL Reference
@Subhead@<:s><:#360,9360>Lists by Type
<:#480,9360>PPL is composed of basically five different token types. They are constants, functions, statements, types, and variables.
@Small_Header@Constant List<:A0>
<:#240,9360>
@Small_Header@Function List<:A5>
<:#240,9360>
@Small_Header@Statement List<:A1>
<:#240,9360>
@Small_Header@Type List<:A6>
<:#240,9360>
@Small_Header@Variable List<:A7>
<:#240,9360>
<:p<* >>
@Subhead@<:#360,9360>Lists by Category
<:s><:#240,9360>Unknown what lists will be necessary at this time.
<+@><:s><:#240,9360>Returns a flag indicating whether or not the user has aborted the display of information.
@Small_Header@<+@><:s><:#259,9360>Syntax
<+@><:#202,9360><:f,QCourier,>ABORT()<:f>
@Indent_List@<+@><:#240,9360> No arguments are required
@Small_Header@<+@><:s><:#259,9360>Return Type & Value
@Indent_List@<:s><:#730,9360><+!>BOOLEAN<-!> If the user has aborted the display of information by answering no to a
<:f,QCourier,>MORE?<:f> prompt or by hitting ^K or ^X display, this function returns
<+!>TRUE<-!>. Otherwise <+!>FALSE<-!> is returned.<-">
@Small_Header@<+@><:s><:#259,9360>Remarks
<:#1455,9360>Unless specifically disabled, the user can abort any display at any time by hitting ^K or ^X or by answering no to a
<:f,QCourier,>MORE?<:f> prompt. If the user does this, PCBoard will not display any further information until the display is reset via the
<+!>RESETDISP<-!> statement. This function should be checked occasionally during long displays of information to determine if the user wants to abort. If the function returns
<+!>TRUE<-!>, you should stop printing information and continue with the next part of the program after using
<+!>RESETDISP<-!>.
@Small_Header@<+@><:s><:#259,9360>Examples
@Example_Text@<+@><:#1274,9360>INTEGER I<**>STARTDISP FCL<**>' While the user has not aborted, continue<**>WHILE (!<+!>ABORT()<-!>) DO<**> PRINTLN "I is equal to ",I<**> INC I<**>ENDWHILE<**>RESETDISP
<+@><:s><:#240,9360>Returns the absolute value of an integer expression.
@Small_Header@<+@><:s><:#259,9360>Syntax
<:#202,9360><:f,QCourier,>ABS(iexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>iexp<:f> Any integer expression.
@Small_Header@<+@><:s><:#259,9360>Return Type & Value
@Indent_List@<:#490,9360><+!>INTEGER<-!> If iexp is greater than or equal to 0, this function returns
<+!>iexp<-!>. Otherwise this function returns <+!>-iexp<-!>.
@Small_Header@<+@><:s><:#259,9360>Remarks
<:#1445,9360>The most significant use of the absolute value function is to determine the difference between two values. For example, you may need to know in a program the difference between 8 and 13. Normal subtraction would yield a result of -5 (8-13). You don't nee
d the mathematical difference though, you need the logical difference between the two integers. The absolute value function will return that. In other words, while 8-13 is -5,
<+!>ABS(8-13)<-!> is 5, which may be a more desirable result in many cases. Also, it is easier to code and understand than this:
@Example_Text@<:s><:#474,9360>INTEGER D<**>LET D = 8-13<**>IF (D << 0) LET D = -D
@Small_Header@<+@><:s><:#259,9360>Examples
@Example_Text@<:#1274,9360>INTEGER num<**>' Loop while num is << 6 or num <;> 10<**>' ... ABS(4-8)=4 ABS( 5-8)=3 ABS( 6-8)=2 ABS( 7-8)=1<**>' ABS(9-8)=1 ABS(10-8)=2 ABS(11-8)=3 ABS(12-8)=4 ...<**>WHILE (<+!>ABS(num-8)<-!> <;> 2) DO<**> PRINTLN "Enter a number from 6 to 10:"<**>
INPUT "Number",num<**>ENDWHILE
@Example_Text@<+@><:#1116,9360>INTEGER i, r<**>' Generate 10 random numbers from -5 to 5<**>' Print each number and it's absolute value<**>FOR i = 1 TO 10<**> LET r = RANDOM(10)-5<**> PRINTLN "The absolute value of ",r," is ",<+!>ABS(r)<-!><**>NEXT
@Indent_List@<:#720,9360> <:f,QCourier,>minutes<:f> An integer expression containing the number of minutes that the users time left should be adjusted by. A value greater than 0 will add time; a value less than 0 will deduct time.
@Small_Header@<:s><:#259,9360>Remarks
<:#2400,9360>Use this statement to reward (or penalize) the user with more (or less) time based on any condition or event you wish. However, the added/deducted time is only applied to the current call. It will not be remembered after the caller hangs up, except that i
t will be reflected in the time online today. For example, if a caller has a normal daily limit of 30 minutes and you add 15 minutes, they can stay online for up to 45 minutes. If they only stay online for 15 minutes and hangup, they will only have 15 min
utes left at the beginning of the next call, not 30; the added time isn't saved. If they stay online for 40 minutes though, it will have given them their entire normal allotment of time plus 10 of the 15 extra minutes. If they try to call back to use thei
r last 5 minutes they will not be able to because PCBoard will see that they've used their entire daily time limit plus 10 minutes. The last 5 minutes wasn't saved.
@Small_Header@<:s><:#259,9360>Examples
@Example_Text@<:#2054,9360>STRING yn<**>INPUTYN "Do you wish to gamble 5 minutes for 10",yn,@X0E<**>IF (yn = YESCHAR()) THEN<**> IF (RANDOM(1) = 1) THEN<**> PRINTLN "You *WON*! 10 extra minutes awarded . . ."<+!><**> ADJTIME 10<-!><**> ELSE<**> PRINTLN "You lost. Sorry,
but I have to take 5 minutes now . . ."<+!><**> ADJTIME -5<-!><**> ENDIF<**>ELSE<**> PRINTLN "Chicken! :)"<**>ENDIF
@Small_Header@<:s><:#259,9360>See Also
<:s><:#240,9360>
<:s><:p<* >>
@Subhead@<:s><:#360,9360>AND() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Calculate the bitwise AND of two integer arguments.
@Small_Header@<:s><:#259,9360>Syntax
<:#202,9360><:f,QCourier,>AND(iexp1,iexp2)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>iexp1<:f> Any integer expression.
@Indent_List@<:#240,9360> <:f,QCourier,>iexp2<:f> Any integer expression.
@Small_Header@<+@><:s><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the bitwise AND of iexp1 and iexp2.
@Small_Header@<:s><:#259,9360>Remarks
<:#960,9360>This function may be used to clear selected bits in an integer expression by ANDing the expression with a mask that has the bits to clear set to 0 and the bits to ignore set to 1. Another use is to calculate the remainder of a division operation by a power
of two by ANDing the dividend with the power of two minus one.
@Small_Header@<:s><:#259,9360>Examples
@Example_Text@<:#652,9360>' Clear the high word, keeping only the low word<**>PRINTLN "07FFFFFFFh AND 0FFFFh = ",<+!>AND(07FFFFFFFh,0FFFFh)<-!><**>' In this case 123%16 = AND(123,15) (15 = 1111b)<**>PRINTLN "The remainder of 123 divided by 16 is ",<+!>AND(123,1111b)<-!>
<:s><:#240,9360>Report the status of ANSI availability with the current caller.
@Small_Header@<:s><:#259,9360>Syntax
<:#202,9360><:f,QCourier,>ANSION()<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:s><:#259,9360>Return Type and Value
@Indent_List@<:s><:#485,9360><+!>BOOLEAN<-!> If the caller can support ANSI then <+!>TRUE<-!> is returned, otherwise
<+!>FALSE<-!> is returned.
@Small_Header@<:s><:#259,9360>Remarks
<:#1940,9360>This function will return <+!>TRUE<-!> if the caller has ANSI capabilities. This could have been determined one of two ways. If the user answered yes to the
<:f,QCourier,>Do you want graphics?<:f> prompt this function will return
<+!>TRUE<-!>. If the user answered no, there is still a chance that the user has ANSI capabilities; PCBoard will interrogate the remote computer to find out if ANSI is available. If it is, this function will return
<+!>TRUE<-!>. Finally, if the user answered no and PCBoard was unable to detect ANSI at login this function will return
<+!>FALSE<-!>. There is still a chance that the user could support ANSI but the only safe approach at this point is to assume that there is no ANSI available.
@Small_Header@<:s><:#259,9360>Examples
@Example_Text@<:#168,9360>IF (<+!>ANSION()<-!>) PRINTLN "You have ANSI support available!"
<:s><:#240,9360>Position the cursor anywhere on the screen using an ANSI positioning escape sequence.
@Small_Header@<:s><:#259,9360>Syntax
<:#202,9360><:f,QCourier,>ANSIPOS xpos, ypos<:f>
@Indent_List@<:#480,9360> <:f,QCourier,>xpos<:f> An integer expression with the screen column (x position) in which to place the cursor. Valid columns are 1 through 80.
@Indent_List@<:#480,9360> <:f,QCourier,>ypos<:f> An integer expression with the screen row (y position) on which to place the cursor. Valid rows are 1 through 23.
@Small_Header@<:s><:#259,9360>Remarks
<:#965,9360>This statement will position the cursor to the specified (X,Y) coordinate on the screen but only if the current caller has ANSI support. If you are writing a program that will require ANSI positioning, check the value of the
<+!>ANSION()<-!> function. If ANSI is not available, this statement will be ignored.
@Small_Header@<:s><:#259,9360>Examples
@Example_Text@<:#1422,9360>CLS<**>IF (ANSION()) THEN<+!><**> ANSIPOS 1,1<-!><**> PRINTLN "This starts at (1,1)"<+!><**> ANSIPOS 3,3<-!><**> PRINTLN "This starts at (3,3)"<+!><**> ANSIPOS 2,2<-!><**> PRINTLN "And *THIS* starts at (2,2)"<**>ENDIF
<:s><:#240,9360>Converts a character to it's ASCII code.
@Small_Header@<:s><:#259,9360>Syntax
<:#202,9360><:f,QCourier,>ASC(sexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>sexp<:f> Any string expression.
@Small_Header@<+@><:s><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns the ASCII code of the first character of sexp (1-255) or 0 if sexp is an empty string.
@Small_Header@<:s><:#259,9360>Remarks
<:s><:#960,9360>In other languages (such as BASIC) you can have any of the 256 possible ASCII codes (0-255) in a string. In PPL you are limited to 255 codes (1-255) because ASCII 0 is used to terminate strings and can't appear in the middle of a string. So, if you ever g
et a 0 returned from this function, it is because you passed it an empty string.
@Small_Header@<:s><:#259,9360>Examples
@Example_Text@<:#652,9360>PRINTLN "The ASCII code for S is ",<+!>ASC("S")<-!><**>' Convert a lowercase s to uppercase<**>STRING s<**>LET s = CHR(<+!>ASC("s")<-!>-<+!>ASC("a")<-!>+<+!>ASC("A")<-!>)
<:#1210,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to automatically answer themselves if left alone for 20 seconds. It can be especially useful if you are writing a program that should work with automated systems; use the
<+!>AUTO<-!> constant and the question will automatically be answered after 20 seconds just in case the automation system doesn't know what to do with it.
@Small_Header@<:s><:#259,9360>Examples
@Example_Text@<:#642,9360>STRING ans<**>LET ans = NOCHAR()<**>INPUTSTR "Run program now",ans,@X0E,1,"",<+!>AUTO<-!>+YESNO<**>IF (ans = NOCHAR()) END
<:#240,9360>Convert two byte-sized arguments into a single word-sized argument.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>B2W(iexp1,iexp2)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>iexp1<:f> Any integer expression with a value between 000h and 0FFh.
@Indent_List@<:#240,9360> <:f,QCourier,>iexp2<:f> Any integer expression with a value between 000h and 0FFh.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns a word-sized value between 00000h and 0FFFFh. The return value is computed by the following expression:
<:f160,QCourier,>iexp1+iexp2*0100h<:f>.
@Small_Header@<:#259,9360>Remarks
<:#965,9360>It is sometimes necessary to combine two bytes together to form a word. This function simplifies that process, and speeds it up a little as well by doing it internally instead of requiring you to perform the arithmetic yourself. It can be especially usefu
l when used with the <+!>DOINTR<-!> statement.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>' This line will display 25 *'s at the current screen position<**>' NOTES: 10h is the Video BIOS interrupt<**>' B2W(ASC("*"),09h) is the char to print and the service number<**>' 0007h is video page 0, attribute 7<**>' 25 is the num
ber of characters to print<**>' All others are 0 and not needed for this function<**>DOINTR 10h,<+!>B2W(09h,ASC("*"))<-!>,0007h,25,0,0,0,0,0,0
@Small_Header@<:#259,9360>See Also
<:#240,9360><+!>DOINTR <+">Statement<-"><-!><-">
<:p<* >>
@Subhead@<:#360,9360>BACKUP <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Move the cursor backward a specified number of columns.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>BACKUP numcols<:f>
@Indent_List@<:#480,9360> <:f,QCourier,>numcols<:f> An integer expression of the number of columns to move backward. Valid values are 1 through 79.
@Small_Header@<:#259,9360>Remarks
<:#1925,9360>This statement will move the cursor backward, nondestructively, a specified number of columns. It will work with or without ANSI. If ANSI is available (as reported by the
<+!>ANSION()<-!> function) then it will use an ANSI positioning command; otherwise it will use the specified number of backspace characters. ANSI is usually faster, but backspace characters will get the job done. Note that you cannot use this function to
move beyond column 1; to do so would require ANSI. So, if the cursor is already in column 1 this statement will have no effect. And if the cursor is in column 80 the maximum you could move backward would be 79 (column 80 - 79 columns = column 1).
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>PRINT "Rolling dice -- "<**>FOR i = 1 TO 10<**> LET d1 = RANDOM(5)+1<**> LET d2 = RANDOM(5)+1<**> PRINT d1,"-",d2<+!><**> BACKUP 3<-!><**>NEXT<**>NEWLINE
<:#245,9360>Set the bell flag in a <+!>DISPTEXT<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>2048 = 100000000000b = 4000o = 800h
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>The <+!>DISPTEXT<-!> statement has the ability to sound a bell before displaying the actual text of a prompt. This is useful when you want to get the users attention when displaying information. It sends a ^G (ASCII 7) character to the remote caller and s
ounds the alarm on the local computer running PCBoard (unless the alarm has been toggled off). It is the responsibility of the users terminal software to support the ^G.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#326,9360>' Get the users attention and display the closed board prompt<**>DISPTEXT 11,<+!>BELL<-!>+LFAFTER+LFBEFORE
<:#240,9360>Display a specified bulletin number to the user.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>BLT bltnum<:f>
@Indent_List@<:#480,9360> <:f,QCourier,>bltnum<:f> The number of the bulletin to display to the user. Valid values are 1 through the number of bulletins available.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This statement will display a specified bulletin number to the user. The BLT.LST file for the current conference will be searched for the bulletin. If the bulletin number is invalid (less than 1 or greater than the highest bulletin number defined) then no
thing will be displayed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#474,9360>INTEGER num<**>INPUT "Bulletin to view",num<+!><**>BLT num<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360>
<:p<* >>
@Subhead@<:#360,9360>BOOLEAN <+">Type<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Declare one or more variables of type boolean.
@Indent_List@<:#720,9360> <:f,QCourier,>var<:f> The name of a variable to declare. Must start with a letter <[>A-Z] which may be followed by letters, digits <[>0-9] or the underscore <[>_]. May be of any length but only the first 32 characters are used.
@Indent_List@<:#480,9360> <:f,QCourier,>arr<:f> The name of an array variable to declare. The same naming conventions as var are used.
@Indent_List@<:#480,9360> <:f,QCourier,>s<:f> The size (0-based) of an array variable dimension. Any constant integer expression is allowed.
@Small_Header@<:#259,9360>Remarks
<:#1715,9360><+!>BOOLEAN<-!> variables can hold two values: 1 or 0 (<+!>TRUE<-!> or
<+!>FALSE<-!>).<+!> <-!>It is stored internally as a one byte unsigned character. If a
<+!>BOOLEAN<-!> is assigned to or from an <+!>INTEGER<-!> type then the value 1 or 0 is assigned. If a
<+!>BOOLEAN<-!> is assigned to a <+!>STRING<-!> type then it is automatically converted to a string (either "1" or "0"). If a
<+!>STRING<-!></`>is assigned to a <+!>BOOLEAN<-!> then the value of the string will be used; a 0 value will be taken as is, another other value will be converted to 1. All other types, when assigned to or from a
<+!>BOOLEAN<-!>, will be converted to an <+!>INTEGER<-!> first before being assigned to or from the
@Indent_List@<:#480,9360> <:f,QCourier,>lonode<:f> An integer expression containing the low node number to which the message should be broadcast.
@Indent_List@<:#480,9360> <:f,QCourier,>hinode<:f> An integer expression containing the high node number to which the message should be broadcast.
@Indent_List@<:#480,9360> <:f,QCourier,>message<:f> A string expression containing the message text which should be broadcast to the specified nodes.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This PPL statement functions the same as the PCBoard BROADCAST command, which is normally reserved for SysOp security level. This statement allows you to programatically broadcast a message to a range of nodes without giving users the ability to manually b
roadcast at any time they choose.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#948,9360>' Broadcast a message to a specific node<+!><**>BROADCAST 5,5,"This broadcast from "+STRING(PCBNODE())<-!><**>' Broadcast to a range of nodes<**><+!>BROADCAST 4,8,"Stand-by for log off in 10 seconds"<-!><**>' Broadcast to all nodes<**><+!>BROADCAST 1,65535,
"Hello all!"<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360>
<:p<* >>
@Subhead@<+@><:#360,9360>BYE <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Log the user off as though they had typed the BYE command.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>BYE<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1685,9360>There are multiple ways for the user to log off. One is by typing G at the command prompt. That will warn them if they have files flagged for download and (optionally) confirm their selection (incase they accidentally hit G and ENTER). Another is the BYE
command. PCBoard assumes that, if the user typed BYE instead of G, that they really want to log off, didn't type it in accidentally, and want to leave
<+!>now<-!>. The <+!>BYE<-!> statement does just that. It is intended to provide you PPL with the same functionality as many PCBoard prompts where G or BYE can be entered at any point.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>STRING s<**>INPUT "What do you want to do",s<**>IF (s = "G") THEN GOODBYE<**>ELSEIF (s = "BYE") THEN
<:#240,9360>Call (execute) another PPE file from the currently executing PPE.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>CALL filename<:f>
@Indent_List@<:#480,9360> <:f,QCourier,>filename<:f> A string expression containing the complete path and filename of a PPE file to load and execute.
@Small_Header@<:#259,9360>Remarks
<:#2185,9360>It is sometimes convienient to load and run complete programs from other programs, similar to how you process subroutines with
<+!>GOSUB<-!> and <+!>RETURN<-!>. PPL supports running both external EXE and COM files via the
<+!>SHELL<-!> statement and other PPE files via the <+!>CALL<-!> statement.
<+!>CALL<-!> allows you to load and run another PPE file, after which control returns to the first PPE at the statement after the
<+!>CALL<-!>. The second PPE is completely separate from the first. You may pass values to the PPE by tokenizing a string with the
<+!>TOKENIZE<-!> statement. If you need to pass values back to the first PPE, you will need to create some sort of parameter passing convention yourself. For example, you may have the second PPE create a file that has the needed information for the first
PPE.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#474,9360>STRING s<**>INPUT "What PPE file do you wish to run",s<**><+!>CALL "C:\PCB\PPE\"+s+".PPE"<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360><+!>SHELL <+">Statement<-"><-!>
<:p<* >>
@Subhead@<:#360,9360>CALLID() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Access caller ID information returned from caller ID compatible modems.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns a string with caller ID information captured from a caller ID compatible modem.
@Small_Header@<:#259,9360>Remarks
<:#1440,9360>Some areas of the country have an optional service available which will send, to your modem (other other telephone device), the phone number and/or name of the person calling you. This service is known as 'Caller ID'. Some modems are starting to support i
t directly by capturing the information and sending it to you between the first and second rings. It can be very helpful in determining who is calling (or abusing) your BBS or for statistical purposes. This function will return the information if your mod
<+@><:#240,9360>Returns the current caller number.
@Small_Header@<+@><:#259,9360>Syntax
<+@><:#202,9360><:f,QCourier,>CALLNUM()<:f>
@Indent_List@<+@><:#240,9360> No arguments are required
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the caller number of the user online.<-">
@Small_Header@<+@><:#259,9360>Remarks
<:#1210,9360>Everytime a user logs on to the system the system caller number is incremented. This function will return the caller number for use in your PPL applications. It is kept in the main conference MSGS file. Note that the number is not incremented until after
the user has completely logged on to the system so you should generally wait until
<+!>LOGGEDON()<-!> reports <+!>TRUE<-!> before using this function.
@Small_Header@<+@><:#259,9360>Examples
@Example_Text@<+@><:#1274,9360>IF (LOGGEDON() & (<+!>CALLNUM()<-!> = 1000000)) THEN<**> PRINTLN "@BEEP@CONGRATULATIONS!!!"<**> PRINTLN "@BEEP@YOU ARE THE 1,000,000th CALLER!!!"<**> PRINTLN "Upgrading security . . ."<**> GETUSER<**> LET U_SEC = 99<**> PUTUSER<**>ENDIF
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns an integer with the connect speed of the current caller.
@Small_Header@<:#259,9360>Remarks
<:#1680,9360>Should the need arise for you to know what speed the caller is connected to the BBS at, this function will return that information. You should note that this information is not guaranteed accurate. It is the responsibility of the modem to tell PCBoard the
actual connect speed, especially in locked port environments. For example, if your serial port is locked at 38400 bps, the modem can usually be configured to report either the actual connect speed (9600 bps, for example) or the locked port rate (38400 bps
). PCBoard has to trust the modem; if the modem tells it 38400, it will have to live with that, as will your PPL applications.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>IF (<+!>CARRIER()<-!> << 9600) THEN<**> PRINTLN "Sorry, downloads are not permitted at speeds below 9600 bps"<**> END<**>ENDIF
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-">
<:p<* >>
@Subhead@<:#360,9360>CCTYPE() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Determine what the type of a credit card is based on the credit card number.
@Indent_List@<:#240,9360> <:f,QCourier,>ccnum<:f> A string expression with the credit card number that is to be checked.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns a string with the name of the card.
@Small_Header@<:#259,9360>Remarks
<:#1685,9360>PPL can be used to perform some simple credit card validation. This function returns the issuer of a credit card based on the credit card number. For example, a valid credit card number that starts with a "4" is a Visa card, so the string "VISA" will be r
eturned. If a credit card is invalid (<+!>VALCC()<-!> = <+!>FALSE<-!>) or not recognized, then "UNKNOWN" will be returned. Other valid credit card with known types will return the appropriate string. The following card types are recognized by PPL: "DISC
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#2170,9360>PCBoard has built in automatic carrier detecting. What this means is that if someone should hangup unexpectedly, PCBoard will detect it, log it to the callers log, and recycle back to the call waiting screen. Some applications require the ability to turn
this off; for example, a callback verification PPE needs to hangup on the caller and then do more processing. Normally, PCBoard would just recycle at that point. So, just before you start a section of code that should continue regardless of the existence
of a caller online, you should issue a <+!>CDCHKOFF<-!> statement. It will turn off the automatic carrier checking. When you've finished the block where carrier checking has been disabled, issue the
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#2170,9360>PCBoard has built in automatic carrier detecting. What this means is that if someone should hangup unexpectedly, PCBoard will detect it, log it to the callers log, and recycle back to the call waiting screen. Some applications require the ability to turn
this off; for example, a callback verification PPE needs to hangup on the caller and then do more processing. Normally, PCBoard would just recycle at that point. So, just before you start a section of code that should continue regardless of the existence
of a caller online, you should issue a <+!>CDCHKOFF<-!> statement. It will turn off the automatic carrier checking. When you've finished the block where carrier checking has been disabled, issue the
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> Returns a boolean <+!>TRUE<-!> if carrier detect is on,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#725,9360>If you have used <+!>CDCHKOFF<-!> to turn off automatic carrier detect checking PCBoard will not automatically detect and act on a carrier loss. If necessary, this function can be used to detect a carrier loss condition and act appropriately.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>IF (!<+!>CDON()<-!>) THEN<**> LOG "Carrier lost in PPE "+PPENAME(),FALSE<**> HANGUP<**>ENDIF
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-">
<:p<* >>
@Subhead@<+@><:#360,9360>CHAT <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Enter SysOp chat mode.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>CHAT<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1930,9360>One of the features of PCBoard where change is often requested is the operator page facility. Some people want to be able to configure multiple ranges of availability per day, some want a different sounding page bell, longer or shorter page attempts, etc,
etc. This statement, along with the <+!>PAGEON<-!> and <+!>PAGEOFF<-!> statements and the
<+!>PAGESTAT()<-!> function, allow you to implement an operator page in any way desired. Of course, the SysOp may still start a chat with the F10 key or by responding to the default O (operator page) command, and the
<+!>CHAT<-!> statement may be used at anytime (although you'll generally want to avoid starting it unless you've confirmed that the SysOp is available since the user has no way to exit it himself).
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1590,9360>PAGEON<**>FOR i = 1 TO 10<**> PRINT "@BEEP@"<**> DELAY 18<**> IF (KINKEY() = " ") THEN<**>
<:#240,9360>Converts an ASCII code to a character.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>CHR(iexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>iexp<:f> Any integer expression between 0 and 255.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns a one character long string for ASCII codes from 1 to 255 or an empty string for ASCII code 0.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>In other languages (such as BASIC) you can have any of the 256 possible ASCII codes (0-255) in a string. In PPL you are limited to 255 codes (1-255) because ASCII 0 is used to terminate strings and can't appear in the middle of a string. So, if you ever g
et an empty string from this function, it is because you passed it a 0. Any other value will return a valid string with a single character.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>PRINTLN "The ASCII code for S is ",ASC("S")<**>' Convert a lowercase s to uppercase<**>STRING s<**>LET s =
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#2185,9360>PCBoard has the ability to capture screen output to a file for later reference. PPL allows that same ability via the
<+!>OPENCAP<-!> and <+!>CLOSECAP<-!> statements. This could be useful in a program that executes a series of commands in non-stop mode. The process could open a capture file first, execute the commands, close the capture file, then allow the user to view
or download the capture file. <+!>CLOSECAP<-!> closes the capture file and turns off screen capturing. Also, the
<+!>SHOWON<-!> and <+!>SHOWOFF<-!> statements can be used to turn on and off showing information to the screen while allowing that same information (even if not displayed or transmitted via modem) to be captured to a file. The
<+!>SHOWSTAT()<-!> function can be used to check the current status of the
<+!>SHOWON<-!> and <+!>SHOWOFF<-!></`>statements.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2212,9360>BOOLEAN ss<**>LET ss = SHOWSTAT()<**>SHOWOFF<**>OPENCAP "CAP"+STRING(PCBNODE()),ocFlag<**>IF (ocFlag) THEN<**> DIR "U;NS"<+!><**> CLOSECAP<-!><**> KBDSTUFF "FLAG CAP"+STRING(PCBNODE())+CHR(13)<**>ENDIF<**>IF (ss) THEN<**> SHOWON<**>ELSE<**> SHOWOFF<**>
<:#240,9360>Clear the current line from the cursor to the end of the line using the current color.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>CLREOL<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#2400,9360>This statement will work one of two ways depending on the mode the caller is in. If the caller is in graphics mode (or non-graphics ANSI-positioning) then PCBoard will issue the ANSI sequence to clear to the end of the line using the current color. ANSI e
mulators, when written properly, will echo the color all the way to column 80 of the current line when they receive this ANSI sequence. If the user is in non-graphics non-ANSI mode, PCBoard will write sufficient spaces to the display to move to column 80 a
nd then backspace to the original position. Note that this will not clear the 80th column; the reason for this is to always keep the cursor on the current line. If the cursor wrote a space to column 80 and moved to the beginning of the next line it wouldn
't be able to move back up to the previous line without ANSI (which we already know we don't have). This should be adequate for most applications.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>COLOR @X47<**>CLS<**>PRINT "This is some sample text. (This will disappear.)"<**>WHILE (INKEY() = "") DELAY 1<**>BACKUP 22<**>COLOR @X1F<+!><**>CLREOL<-!><**>PRINT "This goes to the end of the line."
@Small_Header@<:#259,9360>See Also
<:#240,9360><+!>CLS <+">Statement<-"><-!>
<:p<* >>
@Subhead@<+@><:#360,9360>CLS <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Clear the screen using the current color.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>CLS<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1680,9360>This statement will work one of two ways depending on the mode the caller is in. If the caller is in graphics mode (or non-graphics ANSI-positioning) then PCBoard will issue the ANSI sequence to clear to the screen using the current color. If the user is
in non-graphics non-ANSI mode, PCBoard will write send an ASCII 12 (form feed) character to the remote terminal in a last ditch effort to clear the remote callers screen. Many terminal programs do support this, but not all, so be aware that callers may see
the ASCII 12 instead of a clear screen.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>COLOR @X47<+!><**>CLS<-!><**>PRINT "This is some sample text. (This will disappear.)"<**>WHILE (INKEY() = "") DELAY 1<**>BACKUP 22<**>COLOR @X1F<**>CLREOL<**>PRINT "This goes to the end of the line."
@Small_Header@<:#259,9360>See Also
<:#240,9360><+!>CLREOL <+">Statement<-"><-!>
<:p<* >>
@Subhead@<+@><:#360,9360>COLOR <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Change the current active color.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>COLOR newcolor<:f>
@Indent_List@<:#480,9360> <:f,QCourier,>newcolor<:f> An integer expression containing the new color to be used by PCBoard and the remote terminal software.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This statement will change the color in use by PCBoard and send the appropriate ANSI sequence to change color to the remote terminal software. Note that this statement will only affect a color change if the user is in graphics mode. If the user is in non-
graphics mode this statement will be ignored.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360><+!>COLOR @X47<-!><**>CLS<**>PRINT "This is some sample text. (This will disappear.)"<**>WHILE (INKEY() = "") DELAY 1<**>BACKUP 22<+!><**>COLOR @X1F<-!><**>CLREOL<**>PRINT "This goes to the end of the line."
@Indent_List@<:#240,9360> <:f,QCourier,>confnum<:f> An integer expression containing the conference number to affect.
@Indent_List@<:#240,9360> <:f,QCourier,>flags<:f> An integer expression containing the flags to set.
@Small_Header@<:#259,9360>Remarks
<:#1685,9360>Each user on the BBS has a set of five flags for each conference that control various settings. These flags control the users registration in a conference, their expired status in a conference, whether or not they have a conference selected, whether or not
they have mail waiting in a conference, and whether or not they have SysOp priviledges in a conference. Any or all of these flags may be set at once. To assist you in using this statement, five predefined constants are available to specify each flag:
<+!>F_REG<-!>, <+!>F_EXP<-!>, <+!>F_SEL<-!>, <+!>F_MW<-!>, and <+!>F_SYS<-!>. To use these constants simply add the ones you need together.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1284,9360>' Automatically register them in selected conferences<**>INTEGER i<**>FOR i = 1 TO 10<**>
<+!>CONFFLAG i,F_REG+F_EXP+F_SEL<-!><**>NEXT<**>FOR i = 11 TO 20<**>
@Indent_List@<:#240,9360> <:f,QCourier,>confnum<:f> An integer expression containing the conference number to affect.
@Indent_List@<:#240,9360> <:f,QCourier,>flags<:f> An integer expression containing the flags to clear.
@Small_Header@<:#259,9360>Remarks
<:#1685,9360>Each user on the BBS has a set of five flags for each conference that control various settings. These flags control the users registration in a conference, their expired status in a conference, whether or not they have a conference selected, whether or not
they have mail waiting in a conference, and whether or not they have SysOp priviledges in a conference. Any or all of these flags may be cleared at once. To assist you in using this statement, five predefined constants are available to specify each flag:
<+!>F_REG<-!>, <+!>F_EXP<-!>, <+!>F_SEL<-!>, <+!>F_MW<-!>, and <+!>F_SYS<-!>. To use these constants simply add the ones you need together.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1284,9360>' Automatically deregister them from selected conferences<**>INTEGER i<**>FOR i = 1 TO 10<**>
<+!>CONFUNFLAG i,F_REG+F_EXP+F_SEL<-!><**>NEXT<**>FOR i = 11 TO 20<**>
@Indent_List@<+@><:#240,9360> No arguments are required
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the color code most recently issued to the ANSI driver.<-">
@Small_Header@<+@><:#259,9360>Remarks
<:#1200,9360>The @X code processor within PCBoard has the ability to save and restore color codes built in. PCBoard accomplishes this by saving the current color whenever it encounters an @X00 and reissuing the color change when it encounters an @XFF. Unfortunately, P
CBoard will only remember one color at a time. With this function you can save and restore as many colors as your application needs.
@Small_Header@<+@><:#259,9360>Examples
@Example_Text@<:#4276,9360>INTEGER cc,x,y<**>COLOR @X0F<**>ANSIPOS 26,23<**>PRINT "Hit the SPACE BAR to continue"<**>WHILE (KINKEY() <<<;> " ") DO<**> CLS<**> LET x = 1+RANDOM(57)<**> LET y = 1+RANDOM(21)<**> PUSH 1+RANDOM(14)<**> GOSUB sub<**> LET cc =
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns an integer with the current conference number.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>This function can be useful in configuring a PPL program to work in different ways in different conferences. As a quick example, we have a PPE file on Salt Air that interfaces with the enter message command. If a user is in certain conferences we prompt t
hem for additional information that we will likely need, otherwise we skip to the normal enter message process. Of course, that's just one example; you are sure to have other uses for it.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>IF (<+!>CURCONF()<-!> = 6) THEN ' The Salt Air beta conference is 6<**> PRINTLN "You are leaving a message in the beta conference."<**> PRINTLN "Be sure to leave your file date and time"<**> PRINTLN "and a complete description of the problem."<**>ENDIF<**>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns an integer with the current security level of the user.
@Small_Header@<:#259,9360>Remarks
<:#1210,9360>Although the users primary security level may be accessed via the
<+!>U_SEC<-!> variable after using the <+!>GETUSER<-!> statement, it is often necessary to know the users security level right now after taking into account whether or not they have expired access, additional security from joining a specific conference, or
additional security from the keyboard. This function will take all variables into account and return the current 'logical' security level.
@Indent_List@<:#720,9360> <:f,QCourier,>var<:f> The name of a variable to declare. Must start with a letter <[>A-Z] which may be followed by letters, digits <[>0-9] or the underscore <[>_]. May be of any length but only the first 32 characters are used.
@Indent_List@<:#480,9360> <:f,QCourier,>arr<:f> The name of an array variable to declare. The same naming conventions as var are used.
@Indent_List@<:#480,9360> <:f,QCourier,>s<:f> The size (0-based) of an array variable dimension. Any constant integer expression is allowed.
@Small_Header@<:#259,9360>Remarks
<:#2915,9360><+!>DATE<-!> variables are stored as julian dates. Valid dates are 0 (a special case to represent an invalid date) and 1 (1 JAN 1900) through 36524 (31 DEC 1999) through 65535 (5 JUN 2079). It is stored internally as a two byte unsigned integer. If a
<+!>DATE<-!> is assigned to or from an <+!>INTEGER<-!> type then the julian date (0-65535) is assigned. If a
<+!>DATE<-!> is assigned to a <+!>STRING<-!> type then it is automatically converted to the following format: "MM/DD/YY", where MM is the two digit month (01-12), DD is the two digit day of the month (01-31), and YY is the two digit year (00-99). If a for
eign language is in use that uses a different date format (for example, "DD/MM/YY" or "YY.MM.DD") then that will be taken into account. If a
<+!>STRING<-!></`>is assigned to a <+!>DATE<-!> then PPL will do it's best to convert the string back to the appropriate julian date. However, dates before 1980 will not be handled correctly because only a two digit year is used in strings. All other type
s, when assigned to or from a <+!>DATE<-!>, will be converted to an
<+!>INTEGER<-!> first before being assigned to or from the <+!>DATE<-!> type.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>DATE<-!> Returns a date for today.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>The date returned is represented internally in a julian format (the number of days since January 1, 1900). It may be used as is (for display, storage or as an argument to another function or statement) or assigned to an integer for arithmetic purposes.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "Today is ",<+!>DATE()<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-">
<:p<* >>
@Subhead@<:#360,9360>DAY() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Extracts the day of the month from a date.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>DAY(dexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>dexp<:f> Any date expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns the day of the month from the specified date expression (dexp). Valid return values are from 1 to 31.
@Small_Header@<:#259,9360>Remarks
<:#485,9360>This function allows you to extract a particular piece of information about a
<+!>DATE<-!> value, in this case the day of the month of the date.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "Today is: ",<+!>DAY(DATE())<-!>
@Indent_List@<:#240,9360> <:f,QCourier,>level<:f> An integer expression with the new debug level.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>PCBoard supports an internal variable that allows debug information to be written to the callers log. Level 0 specified no debug information. Levels 1 through 3 specify different (increasing) levels of debug information. It can also be useful for debuggi
ng your PPL programs. This statement allows you to change the PCBoard debug level on the fly without the need to have the SysOp exit and change it in the BOARD.BAT file.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#632,9360>INTEGER newlvl<**>INPUT "New level",newlvl<**>NEWLINE<**>DBGLEVEL newlvl
@Indent_List@<+@><:#240,9360> No arguments are required
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current debug level.<-">
@Small_Header@<+@><:#259,9360>Remarks
<:#1200,9360>PCBoard supports an internal variable that allows debug information to be written to the callers log. Level 0 specified no debug information. Levels 1 through 3 specify different (increasing) levels of debug information. It can also be useful for debuggi
ng your PPL programs. Using this function you can tie your debug information to a specified debug level of your choosing.
@Small_Header@<+@><:#259,9360>Examples
@Example_Text@<:#168,9360>IF (<+!>DBGLEVEL()<-!> = 1) LOG "Writing DEBUG info for "+PPENAME(),0
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The variable with the value to decrement.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>Many programs require extensive addition and subtraction, and most often, a value is increased or decreased by 1. This statement allows for a shorter, more efficient method of decreasing (decrementing) a value by 1 than subtracting 1 from a variable and as
signing the result to the same variable.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>INTEGER i<**>PRINTLN "Countdown:"<**>LET i = 10<**>WHILE (i <;>= 0) DO<**> PRINTLN "T minus ",i<**>
<:#240,9360>Change the current color to the system default color.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>DEFCOLOR<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>This statement will change the color in use by PCBoard to the system default and send the appropriate ANSI sequence to change color to the remote terminal software. This statement is equivalent to
<+!>COLOR DEFCOLOR()<-!>. Note that this statement will only affect a color change if the user is in graphics mode. If the user is in non-graphics mode this statement will be ignored.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>COLOR @X47<**>CLS<**>PRINT "This is some sample text. (This will disappear.)"<**>WHILE (INKEY() = "") DELAY 1<**>BACKUP 22<**><+!>DEFCOLOR<-!><**>CLREOL<**>PRINT "This goes to the end of the line."
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the system default color as defined in PCBSetup.
@Small_Header@<:#259,9360>Remarks
<:#965,9360>This function is useful in cases where you must pass a color to a statement but you want to honor the SysOp's choice of default color for the system. In that case you cannot use the
<+!>DEFCOLOR<-!> statement because it does not return a value that you can pass to another statement.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>STRING yn<**>DEFCOLOR<**>CLS<**>LET yn = YESCHAR()<**>INPUTYN "Continue",yn,<+!>DEFCOLOR()<-!><**>IF (yn = NOCHAR()) END
<:#240,9360>Used when no special statement parameters or flags are needed and defaults are sufficient.
@Small_Header@<:#259,9360>Value
<:#240,9360>0 = 0b = 0o = 0h
@Small_Header@<:#259,9360>Remarks
<:#720,9360>There are many statements that take special values as parameters or flags as an indication to do some special processing. This constant is meant to be used by itself when you do not need any other special constant value.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>STRING ans<**>LET ans = NOCHAR()<**>INPUTSTR "Run program now",ans,@X0E,1,"YyNn",<+!>DEFS<-!><**>IF (UPPER(ans) = NOCHAR()) END
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-"><-"><-"><-">
<:p<* >>
@Subhead@<+@><:#360,9360>DELAY <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Pause execution for a specified period of clock ticks.
@Indent_List@<:#240,9360> <:f,QCourier,>ticks<:f> An integer expression with the number of clock ticks to pause.
@Small_Header@<:#259,9360>Remarks
<:#1445,9360>It is often desireable to wait for a precise time interval for various purposes. This function will allow you to specify an interval to delay in clock ticks. One clock tick is approximately 1/18.2 of a second. So to delay for approximately one second, yo
u should use <+!>DELAY 18<-!>. The basic formula to use is (seconds to delay*18.2) and then round off to the nearest whole number. Note however that PPL doesn't support floating point arithmetic, so if you want to calculate the delay interval at run time
you should use something like (seconds to delay*182)/10.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>INTEGER i<**>PRINTLN "Countdown:"<**>LET i = 10<**>WHILE (i <;>= 0) DO<**> PRINTLN "T minus ",i<**> DEC i<+!><**> DELAY 18<-!><**>ENDWHILE
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<+@><:#360,9360>DELETE <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Delete a specified file from the disk it resides on.
@Indent_List@<:#240,9360> <:f,QCourier,>file<:f> A string expression with the drive, path and file name to delete.
@Small_Header@<:#259,9360>Remarks
<:#725,9360>It is always a good idea to leave things as you found them (as much as possible). This statement allows you to delete temporary files created by your PPE with the
@Example_Text@<:#3476,9360>INTEGER retcode<**>STRING s<**>FCREATE 1,"TMP.LST",O_WR,S_DB<**>LET s = "START"<**>WHILE (LEN(s) <;> 0) DO<**> LET s = ""<**> PRINTLN "Enter a name or ENTER alone to quit:"<**> INPUT "Name",s<**> IF (LEN(s) <;> 0) FPUTLN 1,s<**>ENDWHILE<**>FCLOSE 1<**>
<:#240,9360>Flag the user online on the current node for deletion.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>DELUSER<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1215,9360>This statement will set the delete user record flag to <+!>TRUE<-!>. This will merely flag PCBSystemManager to pack out the user during the next pack operation. If you want to make sure the user doesn't log back in before being packed out, use
<+!>GETUSER<-!>, set his <+!>U_SEC<-!> and <+!>U_EXPSEC<-!> variables to 0, and use the
<+!>PUTUSER<-!> statement to write the changes to the user record.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1590,9360>GETUSER<**>IF (U_CMNT2 = "BAD USER") THEN<**> PRINTLN "Just a friendly note to say,"<**> PRINTLN "I hope you have a rotten day!"<**> PRINTLN "Proceeding with automatic user record deletion..."<**>
<+!>DELUSER<-!><**> LET U_SEC = 0<**> LET U_EXPSEC = 0<**> PUTUSER<**>ENDIF
@Small_Header@<:#259,9360>See Also
<:#240,9360>
<:p<* >>
@Subhead@<+@><:#360,9360>DIR <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Execute the file directories command with desired sub-commands.
@Indent_List@<:#480,9360> <:f,QCourier,>cmds<:f> A string expression with any desired sub-commands for the file directory command.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>This statement will allow you to access file directories (the F command from the main menu), and any file directory sub-commands, under PPE control. Note that this statement will destroy any previously tokenized string expression. If you have string token
s pending at the time of the <+!>DIR<-!> statment you should save them first and then retokenize after the
@Indent_List@<:#240,9360> <:f,QCourier,>file<:f> A string expression with the file name (or base file name) to display.
@Indent_List@<:#240,9360> <:f,QCourier,>flags<:f> An integer expression with alternate file flags.
@Small_Header@<:#259,9360>Remarks
<:#1210,9360>This statement will allow you to display a file to the user, and optionally to have PCBoard look for alternate security, graphics, and/or language specific files. The flags parameter should be 0 for no alternate searching,
<+!>GRAPH<-!> (1) for graphics specific searching, <+!>SEC<-!> (2) for security specific searching,
<+!>LANG<-!> (4) for language specific searching, or any combination thereof for multiple alternate searches simultaneously.
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> A string expression to display (or %filename or !PPEfile to execute).
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>This statement in intended to allow you to easily display a string to the user and provide some of the functionality of PCBTEXT. If the string to display begins with a percent sign and is followed by a valid file name, then the file will be displayed to th
e caller instead of the string. Alternately, the string could begin with an exclamation mark (and be followed by a legal filename) to run a PPE file.
@Indent_List@<:#240,9360> <:f,QCourier,>rec<:f> An integer expression with the PCBTEXT record number to display.
@Indent_List@<:#240,9360> <:f,QCourier,>flags<:f> An integer expression with display flags.
@Small_Header@<:#259,9360>Remarks
<:#730,9360>This statement will allow you to display any prompt from the PCBTEXT file to the user according to a set of display flags. Valid display flags are
@Indent_List@<:#240,9360> <:f,QCourier,>int<:f> An integer expression with the interrupt number to call (0 through 255).
@Indent_List@<:#720,9360> others Integer expressions with 16-bit register values to pass to the interrupt (ax, bx, cx, dx, si, and di are general purpose registers; ds and es are segment registers; flags is the 80x86 processor status register).
@Small_Header@<:#259,9360>Remarks
<:#1930,9360>This statement allows practically unlimited flexibility in PPL. It allows you to access any system service available via the BIOS (video, disk, time, etc), DOS or other third party interface (DESQview, NETBIOS, IPX/SPX, Btrieve, etc). The possibilities ar
e limited only by your imagination. Values that are returned via register may be accessed via the
<+!>REG...()<-!> functions. The values to pass to specific interrupts will vary by the interrupt and function desired.
<+!>WARNING!!!<-!> The <+!>DOINTR<-!> function can be a very valuable tool when used wisely; it can also be extremely destructive when used improperly (either accidentally or intentionally). Use it at your own risk!
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2370,9360>' Create subdirectory - DOS function 39h<**>INTEGER addr<**>STRING path<**>LET path = "C:\$TMPDIR$"<**>VARADDR path,addr<+!><**>DOINTR 21h,39h,0,0,addr%00010000h,0,0,0,addr/00010000h,0<-!><**>IF (REGCF() & (REGAX() = 3)) THEN<**> PRINTLN "Error: Path not
<:#240,9360>Determine the day of the week of a particular date.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>DOW(dexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>dexp<:f> Any date expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns the day of the week from the specified date expression (dexp). Valid return values are from 0 (Sunday) to 6 (Saturday).
@Small_Header@<:#259,9360>Remarks
<:#730,9360>This function allows you to extract a particular piece of information about a
<+!>DATE<-!> value, in this case the day of the week of the date. The specified date can be any valid
<+!>DATE<-!> expression.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "Today is: ",<+!>DOW(DATE())<-!>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1925,9360>This statement turns off the serial port DTR signal. Most modems take this condition to mean that they should hang up on a caller, and this is how PCBoard uses it. This statement can be used when you need to hangup on a caller but don't want PCBoard to pe
rform it's logoff processing. Simply turn off CD checking and keyboard timeout checking and issue the
<+!>DTROFF<-!> statement. Do whatever processing you want, then turn DTR, keyboard timeout testing, and CD loss testing back on to allow PCBoard to recycle normally. Note that DTR should remain off for a period of time to ensure that the modem has time to
react to it. Consider 1/2 second (about 9 clock ticks) a reasonable delay.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1738,9360>BOOLEAN flag<**>KBDCHKOFF<**>CDCHKOFF<+!><**>DTROFF<-!><**>DELAY 18<**>DTRON<**>SENDMODEM "ATDT5551212" ' Please don't really dial this number!<**>WAITFOR "CONNECT",flag,60<**>IF (!flag) SPRINLN "No connect found in 60 seconds"<**>CDCHKON<**>KBDCHKON
@Small_Header@<:#259,9360>See Also
<:#240,9360><+!>DTRON <+">Statement<-"><-!>
<:p<* >>
@Subhead@<+@><:#360,9360>DTRON <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Turn on the serial port DTR signal.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>DTRON<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>This statement turns on the serial port DTR signal. This statement should be used after you've used the
<+!>DTROFF<-!> statement to hangup the modem when you need to hangup on a caller but don't want PCBoard to perform it's logoff processing. Note that DTR should remain off for a period of time, to ensure that the modem has time to react to it, before turnin
g it back on. Consider 1/2 second (about 9 clock ticks) a reasonable delay.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1738,9360>BOOLEAN flag<**>KBDCHKOFF<**>CDCHKOFF<**>DTROFF<**>DELAY 18<+!><**>DTRON<-!><**>SENDMODEM "ATDT5551212" ' Please don't really dial this number!<**>WAITFOR "CONNECT",flag,60<**>IF (!flag) SPRINLN "No connect found in 60 seconds"<**>CDCHKON<**>KBDCHKON
@Small_Header@<:#259,9360>See Also
<:#240,9360><+!>DTROFF <+">Statement<-"><-!>
<:p<* >>
@Subhead@<:#360,9360>ECHODOTS <+">Constant<-">
@Small_Header@<:#259,9360>Function
<:#245,9360>Set the echo dots flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>1 = 1b = 1o = 1h
@Small_Header@<:#259,9360>Remarks
<:#965,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to disable echoing of user input and instead echo dots in place of the user's input. This is useful in situations where the information being entered is confidential and shouldn't be re
vealed to any other party. A good example of this is the user's password.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This statement may be used to normally terminate PPE execution at any point. If you do not have one in your program one is automatically inserted at the end of your source for you at compile time. Additionally, if your PPL application is being used as a s
cript questionnaire, this statement will save any responses written to channel 0 to the script answer file.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1906,9360>DATE d<**>INTEGER i<**>STRING s<**>LET s = "01-20-93"<**>LET d = s<**>IF (DATE() << d) THEN<**> PRINTLN "Your calendar is off!"<**>
<+!>END<-!><**>ENDIF<**>LET i = d<**>PRINTLN "The seige continues: Day ",DATE()-i+1<+!><**>END<-!>
<:#245,9360>Set the erase line flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>32 = 100000b = 40o = 20h
@Small_Header@<:#259,9360>Remarks
<:#730,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to erase the current line after the user presses ENTER. This is the technique used by the
<+!>MORE<-!> and <+!>WAIT<-!> statements to clean up after themselves.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#326,9360>STRING s<**>INPUTSTR "Press ENTER to continue",s,@X0E,0,"",<+!>ERASELINE<-!>
<:#240,9360>Determine whether or not a file exists.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>EXIST(file)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>file<:f> A string expression with the drive, path and file name to check.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if the file exists on the specified drive and path,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>It is often necessary to check for the existence of a file. For example, you wouldn't want to display or otherwise process a file that doesn't exist. This function will report whether or not a specified file exists on a particular drive and path. The dri
ve will default to the current drive and the path will default to the current directory if not specified.
<:#240,9360>To provide a named constant for the boolean false value in boolean expressions.
@Small_Header@<:#259,9360>Value
<:#240,9360>0 = 0b = 0o = 0h
@Small_Header@<:#259,9360>Remarks
<:#970,9360><+!>BOOLEAN<-!> logic is based on two values: <+!>TRUE<-!> (1) and
<+!>FALSE<-!> (0). The literal numeric constants 0 and 1 may be used in expressions, or you may use the predefined named constants
<+!>TRUE<-!> and <+!>FALSE<-!>. They make for more readable, maintainable code and have no more overhead than any other constant value at run time.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1126,9360>BOOLEAN flag<**>LET flag = TRUE<**>WHILE (!flag) DO<**> INPUTSTR "Text",s,@X0E,60,"ABCDEFGHIJKLMNOPQRSTUVWXYZ ",<+!>UPCASE<-!><**> PRINTLN s<**> IF (s = "QUIT") LET flag =
@Indent_List@<:#240,9360> <:f,QCourier,>chan<:f> An integer expression with the channel to use for the file (0 through 7).
@Indent_List@<:#240,9360> <:f,QCourier,>file<:f> A string expression with the file specification to open.
@Indent_List@<:#240,9360> <:f,QCourier,>am<:f> An integer expression with the desired access mode for the file.
@Indent_List@<:#240,9360> <:f,QCourier,>sm<:f> An integer expression with the desired share mode flags for the file.
@Small_Header@<:#259,9360>Remarks
<:#3870,9360>This statement allows a PPL application to open a file for append access. Often you need to add information to an existing file without destroying the existing information in the file.
<+!>FCREATE<-!> completely destroys the file being opened if it already exists, and
<+!>FOPEN<-!> will simply position you at the beginning of the file where you would overwrite data. This statement will allow you to add the necessary information to the end of a file without destroying the file or any existing information in the file. Th
e chan parameter must be 0 through 7; 0 is reserved for the answer file when a PPL script questionnaire is in use but is available for all other applications. However, it is recommended you avoid channel 0 unless you really need to open 8 files at once. T
he am parameter should be one of the following constant values: <+!>O_RD<-!> (for read access),
<+!>O_WR<-!> (for write access), or <+!>O_RW<-!> (for read/write access). Note that the
<+!>FAPPEND<-!> statement actually requires <+!>O_RW<-!> access; whatever you specify doesn't really matter as it will be overridden by PPL, but you must specify it to maintain compatibility with the
<+!>FCREATE<-!> and <+!>FOPEN<-!> statements. Finally, the sm parameter should be one of the following constants:
<+!>S_DW<-!> (for deny write sharing), or <+!>S_DB<-!> (for deny both sharing). Also, if the file specified doesn't exist, it will automatically be created.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#474,9360><+!>FAPPEND 1,"C:\PCB\MAIN\PPE.LOG",O_RW,S_DB<-!><**>FPUTLN 1,"Ran "+PPENAME()+" on "+STRING(DATE())+" at "+STRING(TIME())<**>FCLOSE 1
@Indent_List@<:#240,9360> <:f,QCourier,>chan<:f> An integer expression with the open channel to close (0 through 7).
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>This statement should be used to close a file channel after it has been created/opened with an
<+!>FCREATE<-!>, <+!>FOPEN<-!>, or <+!>FAPPEND<-!> statement. If you should forget to close your files by the end of your PPL application, PPL will automatically close them for you. However, if you need to process many files, it will usually be required t
hat you open a few at a time and close them before going on to the next set of files.
@Indent_List@<:#240,9360> <:f,QCourier,>chan<:f> An integer expression with the channel to use for the file (0 through 7).
@Indent_List@<:#240,9360> <:f,QCourier,>file<:f> A string expression with the file specification to create and open.
@Indent_List@<:#240,9360> <:f,QCourier,>am<:f> An integer expression with the desired access mode for the file.
@Indent_List@<:#240,9360> <:f,QCourier,>sm<:f> An integer expression with the desired share mode flags for the file.
@Small_Header@<:#259,9360>Remarks
<:#2905,9360>This statement allows a PPL application to force the creation and opening of a file, even if it already exists. Creation means that any information previously in the file (if it already exists) will be lost and you will be starting over with an empty file.
The chan parameter must be 0 through 7; 0 is reserved for the answer file when a PPL script questionnaire is in use but is available for all other applications. However, it is recommended you avoid channel 0 unless you really need to open 8 files at once
. The am parameter should be one of the following constant values:
<+!>O_RD<-!> (for read access), <+!>O_WR<-!> (for write access), or
<+!>O_RW<-!> (for read/write access). Note that the <+!>FCREATE<-!> statement forces the creation of an empt file so it doesn't make much sense to use
<+!>O_RD<-!>, as there is nothing to read, unless you only want to create the file. Finally, the sm parameter should be one of the following constants:
<:#240,9360>Determine whether or not an error has occurred on a channel since last checked.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>FERR(chan)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>chan<:f> An integer expression with the channel to use for the file (0 through 7).
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#490,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if an error has occurred on the specified channel since last checked,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#1440,9360>There are many reasons why errors can occur during file processing. The drive, path or file may not exist, the end of the file may have been reached, the drive may be full, there could be errors with the hardware, and so on. For maximum reliability, you s
hould use the function to check for errors after every file channel statement. PCBoard will automatically handle alerting the user of the error in most cases. All you need is to know that an error occurred so that you may continue processing else where or
<:#240,9360>Get (read) a line from an open file<*7><*7>.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>FGET chan,var<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>chan<:f> An integer expression with the channel to read from (0 through 7).
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The variable into which to read the next line from chan.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This statement is to be used for reading information, a line at a time, from a file that was previously opened with read access. If there are multiple items of information on the line then you must parse them out manually.
<:#245,9360>Set the display field length flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>2 = 10b = 2o = 2h
@Small_Header@<:#259,9360>Remarks
<:#970,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to display the length of an input field using "( )" if the user has ANSI available. If you want to ensure that the user knows how wide the input area is regardless of ANSI support being
available, also use the <+!>GUIDE<-!> constant.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#484,9360>STRING pwd<**>INPUTSTR "Enter id number",pwd,@X0E,4,"0123456789",<+!>FIELDLEN<-!>+GUIDE<**>IF (pwd <<<;> "1234") PRINTLN "Bad id number"
@Indent_List@<:#480,9360> <:f,QCourier,>file<:f> A string expression with the path and file name to access information about.
@Indent_List@<:#480,9360> <:f,QCourier,>item<:f> An integer expression with the desired piece of information (1 through 9) to retrieve about file.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!></`>if file exists or <+!>FALSE<-!> if file doesn't exist if item is 1.
@Indent_List@<:#245,9360><+!>DATE<-!> Returns the date stamp of file if item is 2.
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns one of the following for the specified values of stat:
@Indent_List@<:#240,9360> 4 The size of file in bytes;
@Indent_List@<:#240,9360> 5 The attribute bits of file.
@Indent_List@<:#245,9360><+!>STRING<-!> Returns one of the following for the specified values of stat:
@Indent_List@<:#240,9360> 6 The drive of file;
@Indent_List@<:#240,9360> 7 The path of file;
@Indent_List@<:#240,9360> 8 The base name of file;
@Indent_List@<:#240,9360> 9 The extension of file.
@Indent_List@<:#245,9360><+!>TIME<-!> Returns the time stamp of file if item is 3.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>This function is designed to return information about a file. The file date, time, size and attributes are accessible from DOS. In addition, this function can parse out the drive, path, base name and extension if needed from the complete file specificatio
n. Finally, the <+!>EXIST()<-!> function is duplicated in <+!>FILEINF()<-!>.
@Indent_List@<:#240,9360> <:f,QCourier,>chan<:f> An integer expression with the channel to use for the file (0 through 7).
@Indent_List@<:#240,9360> <:f,QCourier,>file<:f> A string expression with the file specification to open.
@Indent_List@<:#240,9360> <:f,QCourier,>am<:f> An integer expression with the desired access mode for the file.
@Indent_List@<:#240,9360> <:f,QCourier,>sm<:f> An integer expression with the desired share mode flags for the file.
@Small_Header@<:#259,9360>Remarks
<:#2425,9360>This statement allows a PPL application to open a file for read and/or write access and to specify the method of sharing desired. The chan parameter must be 0 through 7; 0 is reserved for the answer file when a PPL script questionnaire is in use but is ava
ilable for all other applications. However, it is recommended you avoid channel 0 unless you really need to open 8 files at once. The am parameter should be one of the following constant values:
<+!>O_RD<-!> (for read access), <+!>O_WR<-!> (for write access), or
<+!>O_RW<-!> (for read/write access). Note that the <+!>O_RD <-!>constant expects the file to already exist; the other open constants will create the file if it already doesn't exist. Finally, the sm parameter should be one of the following constants:
<:#240,9360>Execute a block of statments for a range of values.
@Small_Header@<:#259,9360>Syntax
<:#606,9360><:f,QCourier,>FOR var = start TO end <[>STEP inc]<:f><:f,QCourier,><**> statement(s)<**>NEXT<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The index variable for the loop that will be set to each value.
@Indent_List@<:#240,9360> <:f,QCourier,>start<:f> Any valid PPL expression.
@Indent_List@<:#240,9360> end Any valid PPL expression.
@Indent_List@<:#240,9360> inc Any valid PPL expression. 1 if not specified.
@Small_Header@<:#259,9360>Remarks
<:#1450,9360>A <+!>FOR<-!> loop can consist of one or more statements. At the beginning of the loop the specified variable (var) is initialized to the start value. It is then checked against the end value. If start is greater than end (for positive values of inc) or
less than end (for negative values of inc) then the loop terminates. Otherwise all the statements in the loop are executed in order. At the
<+!>NEXT<-!> statement the inc value (1 if not explicitly defined) is added to var and the loop value is retested as described above.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1442,9360>BOOLEAN p(100)<**>INTEGER i<+!><**>FOR i = 1 TO 100<-!> ' Initialize all to TRUE<**> LET p(i) = TRUE<+!><**>NEXT<-!><**>LET p(1) = FALSE<+!><**>FOR i = 4 TO 100 STEP 2<-!> ' Initialize every other one to FALSE<**> LET p(i) = FALSE<+!><**>NEXT<-!>
<:#240,9360>Move the cursor forward a specified number of columns.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>FORWARD numcols<:f>
@Indent_List@<:#480,9360> <:f,QCourier,>numcols<:f> An integer expression of the number of columns to move forward. Valid values are 1 through 79.
@Small_Header@<:#259,9360>Remarks
<:#2165,9360>This statement will move the cursor forward, nondestructively, a specified number of columns. It will work with or without ANSI. If ANSI is available (as reported by the
<+!>ANSION()<-!> function) then it will use an ANSI positioning command; otherwise it will re-display the specified number of characters that are already on screen. ANSI is usually faster, but re-displaying the existing information will get the job done.
Note that you cannot use this function to move beyond column 80; to do so would require ANSI to move back up if necessary. So, if the cursor is already in column 80 this statement will have no effect. And if the cursor is in column 1 the maximum you could
move forward would be 79 (column 1 + 79 columns = column 80).
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1422,9360>PRINT "PIRNT is wrong"<**>DELAY 5*182/10<**>BACKUP 13<**>PRINT "RI"<+!><**>FORWARD 6<-!><**>PRINT "RIGHT"<**>DELAY 5*182/10<**>NEWLINE<**>WAIT
<:#240,9360>Put (write) a line of a specified width to an open file<*7><*7>.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>FPUT chan,exp,width<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>chan<:f> An integer expression with the channel to write to (0 through 7).
@Indent_List@<:#240,9360> <:f,QCourier,>exp<:f> An expression of any type to evaluate and write to chan.
@Indent_List@<:#480,9360> <:f,QCourier,>width<:f> An integer expression with the width to use to write exp. Valid values are -256 through 256
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>This statement will evalutate an expressions of any type and write the result to the specified channel number. This statement will append a carriage return/line feed sequence to the end of the expression after padding it to the specified width with spaces.
If width is positive, then exp will be written right justified (left padded) to the file. If width is negative, then exp will be written left justified (right padded) to the file.
<:#240,9360>Move the cursor to a fresh line for output.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>FRESHLINE<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#965,9360>Often while displaying information to the screen you will print a certain amount then want to make sure you are on a clean line before continuing. This statement checks to see if you are in column 1 of the current line. If you are, it assumes you are on a
clean line and does nothing. Otherwise, it calls the <+!>NEWLINE<-!> statement for you automatically.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1106,9360>INTEGER i, end<**>LET end = RANDOM(20)<**>FOR i = 1 TO end<**> PRINT RIGHT(RANDOM(10000),8)<**>NEXT<+!><**>FRESHLINE<-!><**>PRINTLN "Now we continue . . ."
@Indent_List@<:#240,9360> <:f,QCourier,>chan<:f> An integer expression with the open channel to rewind (0 through 7).
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>This statement should be used when you need to rewind a file channel after it has been created/opened with an
<+!>FCREATE<-!>, <+!>FOPEN<-!>, or <+!>FAPPEND<-!> statement. Rewinding a file channel will flush file buffers, commit the file to disk, and reposition the file pointer to the beginning of the file. Useful when you need to start over processing a file tha
t may have changed and don't want to close and re-open the file.
<:#245,9360>Set the conference expired access flag in a <+!>CONFFLA<-!><+!>G<-!> or
<+!>CONFUNFLAG<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>2 = 10b = 2o = 2h
@Small_Header@<:#259,9360>Remarks
<:#720,9360>There are five flags per conference maintained for each user. This flag is used to indicate whether or not a user is registered in a specified conference after their subscription expiration date.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#336,9360>CONFUNFLAG 5,F_REG+<+!>F_EXP<-!>+F_SEL ' Clear reg, exp & sel flags from conf 5<**>CONFFLAG 9,F_REG+<+!>F_EXP<-!>+F_SEL ' Set reg, exp & sel flags for conf 9
<:#245,9360>Set the conference mail waiting flag in a <+!>CONFFLA<-!><+!>G<-!> or
<+!>CONFUNFLAG<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>10 = 10000b = 20o = 10h
@Small_Header@<:#259,9360>Remarks
<:#480,9360>There are five flags per conference maintained for each user. This flag is used to indicate whether or not a user has mail waiting in a specified conference.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#336,9360>CONFUNFLAG 5,<+!>F_MW<-!> ' Clear mail waiting flag from conf 5<**>CONFFLAG 9,<+!>F_MW<-!> ' Set mail waiting flag for conf 9
<:#245,9360>Set the conference registration flag in a <+!>CONFFLA<-!><+!>G<-!> or
<+!>CONFUNFLAG<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>1 = 1b = 1o = 1h
@Small_Header@<:#259,9360>Remarks
<:#480,9360>There are five flags per conference maintained for each user. This flag is used to indicate whether or not a user is registered in a specified conference.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#336,9360>CONFUNFLAG 5,<+!>F_REG<-!>+F_EXP+F_SEL ' Clear reg, exp & sel flags from conf 5<**>CONFFLAG 9,<+!>F_REG<-!>+F_EXP+F_SEL ' Set reg, exp & sel flags for conf 9
<:#245,9360>Set the conference selected flag in a <+!>CONFFLA<-!><+!>G<-!> or
<+!>CONFUNFLAG<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>4 = 100b = 4o = 4h
@Small_Header@<:#259,9360>Remarks
<:#480,9360>There are five flags per conference maintained for each user. This flag is used to indicate whether or not a user has a specified conference selected for message scans.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#336,9360>CONFUNFLAG 5,F_REG+F_EXP+<+!>F_SEL<-!> ' Clear reg, exp & sel flags from conf 5<**>CONFFLAG 9,F_REG+F_EXP+<+!>F_SEL<-!> ' Set reg, exp & sel flags for conf 9
<:#245,9360>Set the conference SysOp access flag in a <+!>CONFFLA<-!><+!>G<-!> or
<+!>CONFUNFLAG<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>8 = 1000b = 10o = 8h
@Small_Header@<:#259,9360>Remarks
<:#480,9360>There are five flags per conference maintained for each user. This flag is used to indicate whether or not a user has conference SysOp access in a specified conference.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#336,9360>CONFUNFLAG 5,<+!>F_SYS<-!> ' Remove (unflag) conf sysop access from conf 5<**>CONFFLAG 9,<+!>F_SYS<-!> ' Grant (flag) conf sysop access for conf 9
<:#240,9360>Access the value of an environment variable.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>GETENV(name)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>name<:f> A string expression with the name of the environment variable to access.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the value of the environment variable specified by name.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function allows you to access the value of any environment variable set at the time that PCBoard was started. So, for example, the PATH environment variable could be used to access data files somewhere on the path.
<:#245,9360>Retrieve a token from a previous <+!>TOKENIZE<-!> statement.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>GETTOKEN var<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> Variable to store the retrieved token in.
@Small_Header@<:#259,9360>Remarks
<:#1700,9360>One of the strongest features of PCBoard is it's ability to take a series of stacked parameters from a command line and use them all at once instead of requiring the user to navigate a series of menus and select one option at each step of the way. The
<+!>TOKENIZE<-!> statement is the PPL equivalent of what PCBoard uses to break a command line into individual commands (tokens). The number of tokens available may be accessed via the
<+!>TOKCOUNT()<-!> function, and each token may be accessed, one at a time, by the
<+!>GETTOKEN<-!> statement and/or the <+!>GETTOKEN()<-!> function.
<:#245,9360>Retrieve a token from a previous <+!>TOKENIZE<-!> statement.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>GETTOKEN()<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns the next available token from the most recent
<+!>TOKENIZE<-!> statement.
@Small_Header@<:#259,9360>Remarks
<:#1700,9360>One of the strongest features of PCBoard is it's ability to take a series of stacked parameters from a command line and use them all at once instead of requiring the user to navigate a series of menus and select one option at each step of the way. The
<+!>TOKENIZE<-!> statement is the PPL equivalent of what PCBoard uses to break a command line into individual commands (tokens). The number of tokens available may be accessed via the
<+!>TOKCOUNT()<-!> function, and each token may be accessed, one at a time, by the
<+!>GETTOKEN<-!> statement and/or the <+!>GETTOKEN()<-!> function.
<+@><:#240,9360>Fill predeclared variables with values from user record.
@Small_Header@<+@><:#259,9360>Syntax
<+@><:#202,9360><:f,QCourier,>GETUSER<:f>
@Indent_List@<+@><:#240,9360> No arguments are required
@Small_Header@<+@><:#259,9360>Remarks
<+@><:#730,9360>There are many predeclared variables which may be used to access and change user information. However, their values are undefined until you use the
<+!>GETUSER<-!> statement, and any changes you make don't take hold until you use the
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the column (1-80) of the cursor on screen.
@Small_Header@<:#259,9360>Remarks
<:#725,9360>This function is used to query the ANSI emulator in PCBoard the current X position of the cursor. It may be used for saving the cursor position for future use or for saving the horizontal cursor position while changing the vertical position with the
<+!>ANSIPOS<-!> statement.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#3338,9360>INTEGER x,y<**>STRING s<**><**>WHILE (UPPER(s) <<<;> "QUIT") DO<**><**> INPUT "Text",s<**> PRINTLN " - ",s<**><**> LET x =
<+!>GETX()<-!><**> LET y = GETY()<**> IF (y = 23) THEN<**> CLS<**> LET x =
<+!>GETX()<-!><**> LET y = GETY()<**> ENDIF<**><**> ANSIPOS 40,23<**> PRINT "@X8Fs=",s<**> ANSIPOS x,y<**><**>ENDWHILE
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the row (1-23) of the cursor on screen.
@Small_Header@<:#259,9360>Remarks
<:#725,9360>This function is used to query the ANSI emulator in PCBoard the current Y position of the cursor. It may be used for saving the cursor position for future use or for saving the verticle cursor position while changing the horizontal position with the
<+!>ANSIPOS<-!> statement.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#3338,9360>INTEGER x,y<**>STRING s<**><**>WHILE (UPPER(s) <<<;> "QUIT") DO<**><**> INPUT "Text",s<**> PRINTLN " - ",s<**><**> LET x = GETX()<**> LET y =
<+!>GETY()<-!><**> IF (y = 23) THEN<**> CLS<**> LET x = GETX()<**> LET y =
<:#240,9360>Log the user off as though they had typed the G (goodbye) command.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>GOODBYE<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1445,9360>There are multiple ways for the user to log off. One is by typing G at the command prompt. That will warn them if they have files flagged for download and (optionally) confirm their selection (incase they accidentally hit G and ENTER). Another is the BYE
command. PCBoard assumes that, if the user typed BYE instead of G, that they really want to log off, didn't type it in accidentally, and want to leave
<+!>now<-!>. The <+!>GOODBYE<-!> statement performs the same processing as the PCBoard G command.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>STRING s<**>INPUT "What do you want to do",s<**>IF (s = "G") THEN
<+!>GOODBYE<-!><**>ELSEIF (s = "BYE") THEN BYE<**>ELSE KBDSTUFF s<**>ENDIF
<:#240,9360>Transfer program control and save the return information.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>GOSUB label<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>label<:f> The label to which control should be transferred.
@Small_Header@<:#259,9360>Remarks
<:#1215,9360>It is often necessary to perform an indentical set of instructions several times in a program. This leaves you with two choices. One, rewrite the code several times (and hope you do it right each time), or two, write it once as a subroutine, then use
<+!>GOSUB<-!> to run it. This statement will save the address of the next line so that a
<+!>RETURN<-!> statement at the end of the subroutine can instruct PPL to resume execution with the line following the
<+!>GOSUB<-!>.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2370,9360>STRING Question, Answer<**>LET Question = "What is your street address ..."<+!><**>GOSUB ask<-!><**>LET Question = "What is your city, state and zip ..."<+!><**>GOSUB ask<-!><**>END<**><**>:ask ' Sub to ask a question, get an answer, and log them to a file<**>
@Indent_List@<:#240,9360> <:f,QCourier,>label<:f> The label to which control should be transferred.
@Small_Header@<:#259,9360>Remarks
<:#1700,9360><+!>GOTO<-!> is an essential part of just about every programming language, and it is also an overused part of every one of those languages. When you need to make a decision and alter program flow based on some condition it is a necessary evil. For exampl
e, it is very useful in getting out of deeply nested loops when a critical error of some sort occurs. For the most part, avoid it if at all possible. Look for other options to write your program, such as block
<+!>IF<-!>, <+!>WHILE<-!>, and <+!>FOR<-!> statements. They are much easier to understand and maintain than code with
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns a letter indicating the current graphics supported.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This function will return one of four possible responses. "N" will be returned if no graphics support is currently available. "A" will be returned for non-graphics users that do have ANSI support available for positioning. "G" will be returned for users
who support full ANSI graphics. Finally, "R" will be returned for users who support RIPscrip.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1146,9360>IF (<+!>GRAFMODE()<-!> = "R") THEN PRINT "RIPscrip"<**>ELSE IF (<+!>GRAFMODE()<-!> = "G") THEN PRINT "Full ANSI"<**>ELSE IF (<+!>GRAFMODE()<-!> = "A") THEN PRINT "ANSI positioning"<**>ELSE IF (<+!>GRAFMODE()<-!> = "N") THEN PRINT "No"<**>ELSE
<:#245,9360>Set the graphics specific file search flag in a <+!>DISPFILE <-!>statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>1 = 1b = 1o = 1h
@Small_Header@<:#259,9360>Remarks
<:#970,9360>The <+!>DISPFILE<-!> statement will allow you to display a file to the user, and optionally to have PCBoard look for alternate security, graphics, and/or language specific files. This flag instructs PCBoard to search for alternate graphics files (ANSI or R
IPscrip) via the G and R suffix. The current graphics mode may be obtained with the
<+">Statement<-">, GRAFMODE() <+">Function<-">, LANG <+">Constant<-">, SEC
<+">Constant<-"><-!><-">
<:p<* >>
@Subhead@<:#360,9360>GUIDE <+">Constant<-">
@Small_Header@<:#259,9360>Function
<:#245,9360>Set the display input guide flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>4 = 100b = 4o = 4h
@Small_Header@<:#259,9360>Remarks
<:#970,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to display the length of an input field, regardless of ANSI availability, if you use this constant with the
<+!>FIELDLEN<-!> constant. If ANSI is not available and this constant is used, the user will see the input field width marked using "(---)" above the input field.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#484,9360>STRING pwd<**>INPUTSTR "Enter id number",pwd,@X0E,4,"0123456789",FIELDLEN+<+!>GUIDE<-!><**>IF (pwd <<<;> "1234") PRINTLN "Bad id number"
<:#240,9360>Hangup on the user and perform abnormal logoff processing.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>HANGUP<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This statement is useful in situations where you need to get the caller off immediately without any delay or notice. It will hangup on the caller, do all logoff processing, and log an abnormal logoff to the callers log.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>STRING s<**>INPUT "What do you want to do",s<**>IF (s = "G") THEN
<+!>GOODBYE<-!><**>ELSEIF (s = "BYE") THEN BYE<**>ELSEIF (s = "HANG") THEN HANGUP<**>ELSE KBDSTUFF s<**>ENDIF
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the path of the PCBoard help files.
@Small_Header@<:#259,9360>Remarks
<:#480,9360>This function will return the path where help files are located as defined in PCBSetup. This can be useful when you want to add system help capabilities to your PPE application.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>PRINTLN "HELP FOR THE R (READ) COMMAND:"<**>PRINTLN "------------------------------"<**>NEWLINE<**>DISPFILE
<+!>HELPPATH()<-!>+"HLPR",GRAPH+LANG+SEC
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>HIGHASCII <+">Constant<-">
@Small_Header@<:#259,9360>Function
<:#245,9360>Set the allow high ASCII flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
<:#725,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to allow high ASCII characters to be input regardless of the valid character string specified, but only if the SysOp has disabled the high ASCII filter in PCBSetup.
<:#240,9360>Convert an integer to a string in a specified number base.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>I2S(int,base)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>int<:f> Any integer expression to convert to string format.
@Indent_List@<:#240,9360> <:f,QCourier,>base<:f> An integer expression with the number base (2 through 36) to convert to.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the int converted to a string in the specified number base.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>People work with decimal (base 10) numbers, whereas computers work with binary (base 2) numbers. It is often more convienient to display numbers in a format other than decimal for clarity, compactness, or other reasons. This function will convert a number
to string format in any number base from 2 to 36. So, <+!>I2S(10,2)<-!> would return a string of "1010";
<+!>I2S(35,36)<-!> would return "Z". For more information on number bases, consult
<:N737425047,SDR,65535,3,1
Reference number base theory
>
.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#800,9360>INTEGER i,num<**>INPUTINT "Enter a number (decimal)",num,@X0E<**>FOR i = 2 TO 36<**> PRINTLN num," base 10 = ",<+!>I2S(num,i)<-!>," base ",i<**>NEXT
<:#240,9360>Execute one or more statments if a condition is true.
@Small_Header@<:#259,9360>Syntax
<:#2260,9360><:f,QCourier,>IF (bexp) statement<**><:f>-or-<**><:f,QCourier,>IF (bexp) THEN<**> statement(s)<**><[>ELSEIF (bexp) THEN] ' optional in a block IF<**><[> statement(s)]<**><[>ELSEIF (bexp) THEN] ' you may have multiple ELSEIF statement(s)<**><[> statement(
s)]<**><[>ELSE] ' optional in a block IF<**><[> statement(s)]<:f><:f,QCourier,><**>ENDIF<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>bexp<:f> Any boolean expression.
@Indent_List@<:#240,9360> <:f,QCourier,>statement<:f> Any valid PPL statement.
@Small_Header@<:#259,9360>Remarks
<:#2445,9360>The <+!>IF<-!> statement supports two types of structures: logical and block. A logical
<+!>IF<-!> statement is a single statement; if a condition is <+!>TRUE<-!>, execute a single statement. A block
<+!>IF<-!> can be one or more statements with multiple conditions to test for. The start of a block
<+!>IF <-!>loop is differentiated from a logical <+!>IF<-!></`>loop by the
<+!>THEN<-!> keyword immediately after the condition. In a block
<+!>IF<-!> statement the first condition to evaluate to <+!>TRUE<-!> will be executed, after which control will be transferred to the statement following the
<+!>ENDIF<-!>. If none of the conditions are <+!>TRUE<-!> by the time an
<+!>ELSE<-!> statement is reached then the statements between the
<+!>ELSE<-!> and <+!>ENDIF<-!> will be processed. If none of the conditions are
<+!>TRUE<-!> and an <+!>ELSE<-!> statement is never found then none of the conditions will be executed; instead, control will be transferred to the statement after the
<+!>ENDIF<-!>.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1590,9360><+!>IF (CURSEC() << 10)<-!> END ' Insufficient security, terminate execution<+!><**>IF (CURSEC() << 20) THEN<-!><**> PRINTLN "Your security is less than 20"<+!><**>ELSEIF (CURSEC() <;> 30) THEN<-!><**> PRINTLN "Your security is greater than 30"<+!><**>ELS
EIF (CURSEC() = 25) THEN<-!><**> PRINTLN "Your security is 25"<+!><**>ELSE<-!><**> PRINTLN "Your security is level",CURSEC()<+!><**>ENDIF<-!>
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The variable with the value to increment
@Small_Header@<:#259,9360>Remarks
<:#960,9360>Many programs require extensive addition and subtraction, and most often, a value is increased or decreased by 1. This statement allows for a shorter, more efficient method of increasing (incrementing) a value by 1 than adding 1 to a variable and assigning
the result to the same variable.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>INTEGER i<**>PRINTLN "Countdown:"<**>LET i = 0<**>WHILE (i <<= 10) DO<**> PRINTLN "T plus ",i<**>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns a single character for displayable characters or a string for cursor movement and function keys.
@Small_Header@<:#259,9360>Remarks
<:#1440,9360>This function will return a single character long string for most key presses. Additionally, it will return key names for function keys and cursor movement keys if it finds an ANSI sequence or DOORWAY mode sequence. It will return keystrokes from both the
remote caller as well as the local BBS node. However, realize that many function keys are reserved by PCBoard for BBS related uses and may not be available for your applications that require SysOp input.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1906,9360>STRING key<**>WHILE (key <<<;> CHR(27)) DO<**> LET key = <+!>INKEY()<-!><**> IF (LEFT(key,5) = "SHIFT") THEN<**> PRINTLN "It was a shifted key"<**> ELSEIF (LEFT(key,4) = "CTRL") THEN<**> PRINTLN "It was a control key"<**> ELSEIF (LEFT(key,3) = "AL
T") THEN<**> PRINTLN "It was an alternate key"<**> ENDIF<**> PRINTLN "The key was ",key<**>ENDWHILE
@Indent_List@<:#240,9360> <:f,QCourier,>prompt<:f> A string expression with the prompt to display to the user.
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The variable in which to store the user's input.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This statement will accept any string of input from the user, up to 60 characters maximum length. In addition to displaying the prompt, it will display parenthesis around the input field if the user is in ANSI mode. Because of this, you should generally l
@Indent_List@<:#240,9360> <:f,QCourier,>prompt<:f> A string expression with the prompt to display to the user.
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The variable in which to store the user's input.
@Indent_List@<:#240,9360> <:f,QCourier,>color<:f> An integer expression with the color to display the prompt in.
<:#480,9360>INPUT should be followed by one of the following types (without spaces between the INPUT and type): CC, DATE, INT, MONEY, TIME, or YN.
@Small_Header@<:#259,9360>Remarks
<:#1440,9360>This statement will accept a string of input from the user, with a set of valid characters and up to a maximum length (MAXLEN) determined by the statement in use. In addition to displaying the prompt, it will display parenthesis around the input field if t
he user is in ANSI mode. Because of this, you should generally limit your prompts to a length determined by the following formula: (80-MAXLEN-4). Here are the valid character masks and maximum length values for each of the input statements:
<:#240,9360>
<:t3>
<:#240,9360>
<:#725,9360>* The <+!>INPUTYN<-!> statement valid characters are dependent on the users language selection. Usually they will be "YN" for english language systems. Other letters may be defined for different languages in PCBML.DAT.
@Indent_List@<:#240,9360> <:f,QCourier,>prompt<:f> A string expression with the prompt to display to the user.
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The variable in which to store the user's input.
@Indent_List@<:#240,9360> <:f,QCourier,>color<:f> An integer expression with the color to display the prompt in.
@Indent_List@<:#240,9360> <:f,QCourier,>len<:f> An integer expression with maximum length of text to input.
@Indent_List@<:#240,9360> <:f,QCourier,>valid<:f> A string expression with the valid characters that the user may enter.
@Indent_List@<:#240,9360> <:f,QCourier,>flags<:f> An integer expression with flags to modify how the statement works.
@Small_Header@<:#259,9360>Remarks
<:#2425,9360>This statement will accept a string of input from the user, up to the length defined. The prompt parameter will be displayed to the user in the specified color before accepting input. Only characters found in the valid parameter will be accepted. However
, the flags parameter may affect how prompt is displayed and the valid characters that are accepted. Individual flags may be added together as needed. Several functions exist to easily specify commonly used valid character masks. They are
@Indent_List@<:#240,9360> <:f,QCourier,>prompt<:f> A string expression with the prompt to display to the user.
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The variable in which to store the user's input.
@Indent_List@<:#240,9360> <:f,QCourier,>color<:f> An integer expression with the color to display the prompt in.
@Indent_List@<:#240,9360> <:f,QCourier,>len<:f> An integer expression with maximum length of text to input.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This statement will accept any string of input from the user, up to the length defined. In addition to displaying the prompt, it will display parenthesis around the input field if the user is in ANSI mode. Because of this, you should generally limit your
<:#240,9360>Find the position of one string within another string.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>INSTR(str,sub)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> A string expression to look for sub in.
@Indent_List@<:#240,9360> <:f,QCourier,>sub<:f> A string expression to search for.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns the 1-based position of sub within str or 0 if sub is not found within str.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function is useful for determining if a particular word or phrase exists in a string. The return value is the position of the sub string within the longer string. The first character of str is position 1, the second is position 2, and so on. If sub
@Indent_List@<:#720,9360> <:f,QCourier,>var<:f> The name of a variable to declare. Must start with a letter <[>A-Z] which may be followed by letters, digits <[>0-9] or the underscore <[>_]. May be of any length but only the first 32 characters are used.
@Indent_List@<:#480,9360> <:f,QCourier,>arr<:f> The name of an array variable to declare. The same naming conventions as var are used.
@Indent_List@<:#480,9360> <:f,QCourier,>s<:f> The size (0-based) of an array variable dimension. Any constant integer expression is allowed.
@Small_Header@<:#259,9360>Remarks
<:#1700,9360><+!>INTEGER<-!> variables are stored as four byte signed long integers. The range of an
<+!>INTEGER<-!> is -2,147,483,648 - +2,147,483,647. An <+!>INTEGER<-!> assignment to a
<+!>STRING<-!> will result in a string with the representation of the number (similar to BASIC's STR$ function and C's ltoa function). A
<+!>STRING<-!> to <+!>INTEGER<-!> assignment will convert the string back to the four byte binary integer value (similar to BASIC's VAL function and C's atol function). If an
<+!>INTEGER<-!> is assigned to or from any other type, an appropriate conversion is performed automatically by PPL.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#158,9360><+!>INTEGER i, year, cardDeck(4*13), matrix(2,2), matrices(3,4,5)<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360><+!>BOOLEAN <+">Type<-">, DATE <+">Type<-">, MONEY <+">Type<-">, STRING
<+">Type<-">, TIME <+">Type<-!><-">
<:p<* >>
@Subhead@<+@><:#360,9360>JOIN <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Execute the join conference command with desired sub-commands.
@Indent_List@<:#480,9360> <:f,QCourier,>cmds<:f> A string expression with any desired sub-commands for the join conference command.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>This statement will allow you to access the join conference (the J command from the main menu), and any join conference sub-commands, under PPE control. Note that this statement will destroy any previously tokenized string expression. If you have string t
okens pending at the time of the <+!>DIR<-!> statment you should save them first and then retokenize after the
<+!>DIR<-!> statement is complete.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#484,9360>STRING yn<**>INPUTYN "Join SysOp conference",yn,@X0E<**>IF (yn = YESCHAR())
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#2650,9360>PCBoard has built in automatic keyboard timeout detecting. What this means is that if someone should remain online for a SysOp defined period of time without typing anything for PCBoard to process, PCBoard will detect it, log it to the callers log, and rec
ycle back to the call waiting screen. Some applications require the ability to turn this off; for example, a process that will take a while without interacting with the caller should turn off keyboard timeout testing to keep PCBoard from thinking that the
user has stopped entering information. Normally, PCBoard would just recycle at that point. So, just before you start a section of code that should continue for a while without user input, you should issue a
<+!>KBDCHKOFF<-!> statement. It will turn off the automatic keyboard timeout checking. When you've finished the block where keyboard timeout checking has been disabled, issue the
<+!>KBDCHKON<-!> statement to turn it back on.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#474,9360><+!>KBDCHKOFF<-!><**>WHILE (RANDOM(10000) <<<;> 0) PRINT "." ' Something to take a long time!<**>KBDCHKON
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#2650,9360>PCBoard has built in automatic keyboard timeout detecting. What this means is that if someone should remain online for a SysOp defined period of time without typing anything for PCBoard to process, PCBoard will detect it, log it to the callers log, and rec
ycle back to the call waiting screen. Some applications require the ability to turn this off; for example, a process that will take a while without interacting with the caller should turn off keyboard timeout testing to keep PCBoard from thinking that the
user has stopped entering information. Normally, PCBoard would just recycle at that point. So, just before you start a section of code that should continue for a while without user input, you should issue a
<+!>KBDCHKOFF<-!> statement. It will turn off the automatic keyboard timeout checking. When you've finished the block where keyboard timeout checking has been disabled, issue the
<+!>KBDCHKON<-!> statement to turn it back on.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#474,9360>KBDCHKOFF<**>WHILE (RANDOM(10000) <<<;> 0) PRINT "." ' Something to take a long time!<+!><**>KBDCHKON<-!>
@Indent_List@<:#480,9360> <:f,QCourier,>file<:f> A string expression with the filename whose contents should be stuffed into the keyboard buffer.
@Small_Header@<:#259,9360>Remarks
<:#965,9360>This statement allows you to feed a series of keystrokes to PCBoard as though they were typed in by the user. This is useful when you need to feed a series of commands to PCBoard one right after another and they would add up to more than 256 characters (th
e maximum buffer size for the <+!>KBDSTUFF<-!> statement).
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> A string expression to stuff into the keyboard buffer for later processing.
@Small_Header@<:#259,9360>Remarks
<:#1925,9360>This statement allows you to feed a series of keystrokes to PCBoard as though they were typed in by the user. This can be especially useful when you are replacing an existing command; add your PPE file to the CMD.LST file so that it takes the place of the
built in command, then have your PPE stuff the original (or modified command) back to the keyboard buffer. PCBoard will then process it as soon as you exit your PPE application. It can also be used when building new commands that should perform several bu
ilt in operations automatically. A maximum of 256 characters at a time can be stuffed into the keyboard buffer. If you need more than this, you should use the
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns a single character for displayable characters or a string for cursor movement and function keys.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>This function will return a single character long string for most key presses. Additionally, it will return key names for function keys and cursor movement keys. It will only return keystrokes from the local BBS node's keyboard. However, realize that man
y function keys are reserved by PCBoard for BBS related uses and may not be available for your applications that require SysOp input.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1906,9360>STRING key<**>WHILE (key <<<;> CHR(27)) DO<**> LET key = <+!>KINKEY()<-!><**> IF (LEFT(key,5) = "SHIFT") THEN<**> PRINTLN "It was a shifted key"<**> ELSEIF (LEFT(key,4) = "CTRL") THEN<**> PRINTLN "It was a control key"<**> ELSEIF (LEFT(key,3) = "A
LT") THEN<**> PRINTLN "It was an alternate key"<**> ENDIF<**> PRINTLN "The key was ",key<**>ENDWHILE
<:#245,9360>Set the language specific file search flag in a <+!>DISPFILE <-!>statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>4 = 100b = 4o = 4h
@Small_Header@<:#259,9360>Remarks
<:#970,9360>The <+!>DISPFILE<-!> statement will allow you to display a file to the user, and optionally to have PCBoard look for alternate security, graphics, and/or language specific files. This flag instructs PCBoard to search for alternate language files via the la
nguage extension. The current language extension may be obtained with the
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#725,9360><+!>STRING<-!> Returns a ".XXX" formatted string where XXX is the extension text (could be 1, 2 or 3 characters long depending on the configuration and language in use).
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function allows you to access the file extension used by SysOp definable and system language specific files. You may use it to create your own filenames that are language specific.
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> A string expression to take the left most characters of.
@Indent_List@<:#480,9360> <:f,QCourier,>chars<:f> An integer expression with the number of characters to take from the left end of str.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns a string with the left most chars characters of str.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This function will return a sub string with the left most chars characters of a specified string. This can be useful in data processing as well as text formatting. If chars is less than or equal to 0 then the returned string will be empty. If chars is gr
eater than the length of str then the returned string will have spaces added to the left to pad it out to the full length specified.
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the length of a string.
@Small_Header@<:#259,9360>Remarks
<:#480,9360>This function will return the length of a string. The value returned will always be between 0 (an empty string) and 256 (the maximum length of a string).
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>STRING s<**>FOPEN 1,"DATA.TXT",O_RD,S_DN<**>WHILE (!FERR(1)) DO<**> FGET 1,s<**> PRINTLN "The length of the current string is ",<+!>LEN(s)<-!><**>ENDWHILE<**>FCLOSE 1
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-"><-"><-">
<:p<* >>
@Subhead@<+@><:#360,9360>LET <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Evaluate an expression and assign the result to a variable.
@Small_Header@<:#259,9360>Syntax
<:#644,9360><:f,QCourier,>LET var = expr<:f><**>-or-<**><:f,QCourier,>var = expr<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> Variable to which the result of expr should be assigned.
@Indent_List@<:#240,9360> <:f,QCourier,>expr<:f> Any valid PPL expression.
@Small_Header@<:#259,9360>Remarks
<:#2450,9360>The <+!>LET<-!> statement supports modes of operation: explicit and implicit. An explicit
<+!>LET<-!> statement always includes all of the parts in the first example above (the
<+!>LET<-!> keyword, the variable, the equal sign, and the expression). An implicit
<+!>LET<-!> statement does not need the <+!>LET<-!> keyword; the format (var = expr) is sufficient. However, the implicit form will not always work. For example, if you had a variable named
<+!>PRINT<-!> (which is also a statement name) you could not use <+!>PRINT = expr<-!>; PPL expects the first word on a line to be a statement name, and if it isn't, it is an implicit
<+!>LET<-!> statement. Since PPL would find the <+!>PRINT<-!> statement first it would try to process the rest of the line as a
<+!>PRINT<-!> statement. This is easily avoided by using the <+!>LET<-!> keyword and making it an explicit
<+!>LET<-!> statement (<+!>LET PRINT = expr<-!>).
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1106,9360>INTEGER i<**>STRING s<**>GETUSER<+!><**>LET U_PWD = "NEWPWD"<**>LET s = "This is a string"<**>LET i = 7*9+9*7<-!><**>PUTUSER
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-">
<:p<* >>
@Subhead@<:#360,9360>LFAFTER <+">Constant<-">
@Small_Header@<:#259,9360>Function
<:#485,9360>Set the extra line feed after prompt flag in a <+!>DISPTEXT<-!>, <+!>INPUTSTR<-!>, or
<+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>256 = 100000000b = 400o = 100h
@Small_Header@<:#259,9360>Remarks
<:#730,9360>The <+!>INPUTSTR<-!>, <+!>PROMPTSTR<-!>, and <+!>DISPTEXT<-!> statements have the ability to send an extra carriage return/line feed after a prompt is displayed automatically and without the need to make a separate call to the
<:#485,9360>Set the line feed before prompt flag in a <+!>DISPTEXT<-!>, <+!>INPUTSTR<-!>, or
<+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>128 = 10000000b = 200o = 80h
@Small_Header@<:#259,9360>Remarks
<:#730,9360>The <+!>INPUTSTR<-!>, <+!>PROMPTSTR<-!>, and <+!>DISPTEXT<-!> statements have the ability to send a carriage return/line feed before a prompt is displayed automatically and without the need to make a separate call to the
@Indent_List@<:#240,9360> <:f,QCourier,>msg<:f> A string expression to write to the callers log.
@Indent_List@<:#490,9360> <:f,QCourier,>left<:f> A boolean expression with value <+!>TRUE<-!> if msg should be left justified,
<+!>FALSE<-!> if msg should be indented six spaces.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>There are two primary uses for this statement. First and foremost, it allows you to keep the SysOp informed of what the user does while using your PPL application. Secondly, it can allow you to track information within your PPE while debugging.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#800,9360>BOOLEAN flag<**>PRINT "Type QUIT to exit..."<**>WAITFOR "QUIT",flag,60<**>IF (!flag)
<+!>LOG "User did not type QUIT",FALSE<-!><**><+!>LOG "***EXITING PPE***",TRUE<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>LOGGEDON() <+"> Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Determine if a user has completely logged on to the BBS.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if the user has completed logging in,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#965,9360>There are some features of PPL that are not available until the user has completely logged in, such as the user variables and functions and the
<+!>CALLNUM()<-!> function. This function will allow you to detect whether or not a user has completely logged in and if selected PPL features are available.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>IF (!<+!>LOGGEDON()<-!>) LOG "USER NOT LOGGED ON",0
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-">
<:p<* >>
@Subhead@<:#360,9360>LOGIT <+">Constant<-">
@Small_Header@<:#259,9360>Function
<:#245,9360>Set the write prompt to callers log flag in a <+!>DISPTEXT<-!> statement.
<:#240,9360>Converts uppercase characters in a string to lowercase.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>LOWER(sexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>sexp<:f> Any string expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns sexp with all uppercase characters converted to lowercase.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>Although "STRING" is technically different from "string" (ie, the computer doesn't recognize them as being the same because one is uppercase and the other is lowercase), it is often necessary to save, display or compare information in a case insensitive for
mat. This function will return a string with all uppercase characters converted to lowercase. So, using the above example,
<:#240,9360>Trim a specified character from the left end of a string.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>LTRIM(str,ch)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression.
@Indent_List@<:#240,9360> <:f,QCourier,>ch<:f> A string with the character to strip from the left end of str.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the trimmed str.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>A common need in programming is to strip leading and/or trailing spaces (or other characters). This function will strip a specified character from the left end of a string and return the trimmed string.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#820,9360>STRING s<**>LET s = " TEST "<**>PRINTLN <+!>LTRIM(s," ")<-!> ' Will print "TEST "<**>PRINTLN
<+!>LTRIM(".....DA"+"TA.....",".")<-!> ' Will print "DATA....."<**>PRINTLN
<+!>LTRIM(".....DA"+"TA....."," ")<-!> ' Will print ".....DATA....."
@Indent_List@<:#240,9360> No arguments are required
<:#480,9360>MASK_ should be followed by one of the following mask types: ALNUM, ALPHA, ASCII, FILE, NUM, PATH, or PWD.
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#490,9360><+!>STRING<-!> Returns a string with a set of characters to use as valid input for an
<+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Remarks
<:#2190,9360>There are many situations in which you will need to use an <+!>INPUTSTR<-!> or
<+!>PROMPTSTR<-!> statement to access the input field length of flags. However, all you need to use a 'standard' set of input characters. These functions provide you with some of the most common valid character masks. They are:
<+!>MASK_ALNUM()<-!> which returns A-Z, a-z, and 0-9; <+!>MASK_ALPHA()<-!> which returns A-Z and a-z;
<+!>MASK_ASCII()<-!> which returns all characters from space (ASCII 32) to tilde (ASCII 126);
<+!>MASK_FILE()<-!> which returns all legal file name characters;
<+!>MASK_NUM()<-!> which returns 0-9; <+!>MASK_PATH()<-!> which returns all legal path name characters; and, finally,
<+!>MASK_PWD()<-!> which returns a set of valid characters for use in passwords.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#820,9360>INTEGER i<**>STRING s<**>INPUTSTR "Enter a number from 0 to 1000",i,@X0E,4,<+!>MASK_NUM()<-!>,DEFS<**>PROMPTSTR 148,s,12,<+!>MASK_PWD()<-!>,ECHODOTS<**>INPUTSTR "Enter your comment",s,@X0E,60,<+!>MASK_ASCII()<-!>,DEFS
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the node limit available to the system running the PPE file.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>Every package of PCBoard purchased comes with a license agreement that limits it to a maximum number of nodes. This node limit restricts various features of PCBoard, such as the WHO display and CHAT functions. This limit is available to your PPL applicati
ons via this function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1274,9360>INTEGER i<**>FOR i = 1 TO <+!>MAXNODE()<-!><**> RDUNET i<**> IF ((UN_STAT() = "A") | (UN_STAT() = "U")) THEN<**> BROADCAST i,i,"Hello, how are you?"<**> IF (PCBNODE() = i) PRINLN "Quit talking to yourself"<**> ENDIF<**>NEXT
@Indent_List@<:#240,9360> <:f,QCourier,>conf<:f> An integer expression with the conference in which to post the message.
@Indent_List@<:#480,9360> <:f,QCourier,>to<:f> A string expression with the user name to which the message should be sent.
@Indent_List@<:#480,9360> <:f,QCourier,>from<:f> A string expression with the user name that the message should be sent from.
@Indent_List@<:#240,9360> <:f,QCourier,>sub<:f> A string expression with the subject of the message.
@Indent_List@<:#480,9360> <:f,QCourier,>sec<:f> A string expression with the desired security for the message ("N"for none or "R" for receiver only).
@Indent_List@<:#480,9360> <:f,QCourier,>pack<:f> A date expression with the packout date for the message (or 0 for no packout date).
@Indent_List@<:#490,9360> <:f,QCourier,>rr<:f> A boolean expression with the return receipt requested flag (<+!>TRUE<-!> to request a return receipt,
<+!>FALSE<-!> otherwise).
@Indent_List@<:#490,9360> <:f,QCourier,>echo<:f> A boolean expression with the echo flag (<+!>TRUE<-!> to echo the message,
<+!>FALSE<-!> otherwise).
@Indent_List@<:#480,9360> <:f,QCourier,>file<:f> A string expression with the path and file name of the text file to use as the message text.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This statement will allow you to leave a message from any user (or any 'name' you wish to use) to any user on your system. This can be useful if you want to notify a user of information that they should download in a QWK packet or that they might miss too
easily as a quick one liner on screen from the PPL.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns the value (0-255) of the next byte from the modem input buffer or -1 if no bytes are pending.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>Any character may be received from the users modem. Normally PCBoard will filter and convert strings (ESC sequences and DOORWAY codes) automatically. However, sometimes this isn't desired and you need to access the incoming bytes directly. This function
will look directly for incoming characters from the modem and return them as a value from 0 to 255. These numbers may be converted to characters with the
<+!>CHR()<-!> function if necessary.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#800,9360>INTEGER byte<**>WHILE (byte <<<;> 27) DO<**> LET byte = <+!>MGETBYTE()<-!><**> PRINTLN "The byte value is ",byte<**>ENDWHILE
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> A string expression to take the left most characters of.
@Indent_List@<:#480,9360> <:f,QCourier,>pos<:f> An integer expression with the position within str to start taking the sub string from.
@Indent_List@<:#240,9360> <:f,QCourier,>chars<:f> An integer expression with the number of characters to take from str.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns a string with the specified number of characters from the specified position of str.
@Small_Header@<:#259,9360>Remarks
<:#1680,9360>This function will return a sub string with the specified number of characters and from the specified position of str. This can be useful in data processing as well as text formatting. The pos parameter may be less than 1 (the beginning of the str) and gr
eater than the length of str; if it is then spaces will be added to the beginning and/or ending as needed. If chars is less than or equal to 0 then the returned string will be empty. If chars is greater than the available length of str then the returned s
tring will have spaces added to the end(s) to pad it out to the full length specified.
<:#240,9360>Extract the minute of the hour from a specified time of day.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>MIN(texp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>texp<:f> Any time expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns the minute of the hour from the specified time expression (texp). Valid return values are from 0 to 59.
@Small_Header@<:#259,9360>Remarks
<:#485,9360>This function allows you to extract a particular piece of information about a
<+!>TIME<-!> value, in this case the minute of the hour of the time of day expression.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "The minute is ",<+!>MIN(TIME())<-!>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns a single character for displayable characters or a string for cursor movement and function keys.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function will return a single character long string for most key presses. Additionally, it will return key names for function keys and cursor movement keys if it encounters ESC sequences or DOORWAY codes. It will only return keystrokes from the remot
e users modem.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1906,9360>STRING key<**>WHILE (key <<<;> CHR(27)) DO<**> LET key = <+!>MINKEY()<-!><**> IF (LEFT(key,5) = "SHIFT") THEN<**> PRINTLN "It was a shifted key"<**> ELSEIF (LEFT(key,4) = "CTRL") THEN<**> PRINTLN "It was a control key"<**> ELSEIF (LEFT(key,3) = "A
LT") THEN<**> PRINTLN "It was an alternate key"<**> ENDIF<**> PRINTLN "The key was ",key<**>ENDWHILE
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the number of minutes the user online has left to use.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function will allow you to access how much time the user has remaining. You could use it to disable certain features at a certain point in their session. Note that this number can be either the minutes left today or this session if the SysOp does not
enforce daily time limits.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#800,9360>IF (<+!>MINLEFT()<-!> <;> 10) THEN<**> KBDSTUFF "D"+CHR(13)<**>ELSE<**> PRINTLN "Sorry, not enough time left to download"<**>ENDIF
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the number of minutes the user online has used this session.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This function will allow you to access how much time the user has used this session. You could use it to allow or disallow certain features before a certain point in their session. Note that this number will always be the minutes used this session regardl
ess of whether or not the SysOp enforces daily time limits.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#800,9360>IF (<+!>MINON()<-!> <;>= 10) THEN<**> KBDSTUFF "D"+CHR(13)<**>ELSE<**> PRINTLN "Sorry, you haven't been on long enough yet to download"<**>ENDIF
@Indent_List@<:#240,9360> <:f,QCourier,>seg<:f> An integer expression with the segment portion of the address.
@Indent_List@<:#240,9360> <:f,QCourier,>off<:f> An integer expression with the offset portion of the address.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns an integer with the complete segment:offset based address.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>The <+!>POKE...<-!> statements and <+!>PEEK...()<-!> functions require full addresses to read from and write to memory. Normally you will know the segment and the offset portions of the address but they will be separate. Although not difficult to integrat
e together, this function automates the process. The values returned can be calculated by the following formula:
<+!>seg*10000h+off<-!>.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "Ticks since midnight",PEEKDW(<+!>MKADDR(0040h,006Ch)<-!>)
@Indent_List@<:#240,9360> <:f,QCourier,>year<:f> An integer expression with the year (1900 through 2079).
@Indent_List@<:#240,9360> <:f,QCourier,>month<:f> An integer expression with the month (1 through 12).
@Indent_List@<:#240,9360> <:f,QCourier,>day<:f> An integer expression with the day of the month (1 through 31).
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>DATE<-!> Returns a date made from the specified year, month and day values.
@Small_Header@<:#259,9360>Remarks
<:#1925,9360>Although PPL does it's best to automatically convert values from one type to another as needed, converting
<+!>STRING<-!> values to <+!>DATE<-!> values presents a special problem because of the year portion of the date. Normally the year is only expressed in a two digit format. This limits the automatic convertion to a single 100 year period. PCBoard uses yea
r values greater than or equal to 80 as 20th century (19XX) dates, and year values less than 80 as 21st century (20XX) dates. Since you may need to access dates prior to 1980 (when processing birthdates, for example), this function allows you to take three
integers (year, month and day) and build any date necessary.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2094,9360>PRINTLN "My birthdate is ",<+!>MKDATE(1967,10,31)<-!><**>INTEGER y,m,d<**>INPUTINT " Your birth year",y,@X0E<**>INPUTINT "Your birth month",m,@X0E<**>INPUTINT " Your birth day",d,@X0E<**>PRINTLN "Your birthdate is ",<+!>MKDATE(y,m,d)<-!><**>IF (<+!>MKDATE(
y,m,d)<-!> << <+!>MKDATE(1967,10,31)<-!>) THEN<**> PRINTLN "You are older than me"<**>ELSE IF (<+!>MKDATE(y,m,d)<-!> <;>
<+!>MKDATE(1967,10,31)<-!>) THEN<**> PRINTLN "I am older than you"<**>ELSE<**> PRINTLN "We are the same age"<**>ENDIF
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the modem connect string.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>PCBoard expects and requires certain information to be reported by the modem anytime a user connects to the BBS. The minimum requirement is a string with the word CONNECT; other information may be included, such as the connect speed, error correction, data
compression, etc. Should your PPL application have need of this information as well, it may be accessed with this function.
@Indent_List@<:#720,9360> <:f,QCourier,>var<:f> The name of a variable to declare. Must start with a letter <[>A-Z] which may be followed by letters, digits <[>0-9] or the underscore <[>_]. May be of any length but only the first 32 characters are used.
@Indent_List@<:#480,9360> <:f,QCourier,>arr<:f> The name of an array variable to declare. The same naming conventions as var are used.
@Indent_List@<:#480,9360> <:f,QCourier,>s<:f> The size (0-based) of an array variable dimension. Any constant integer expression is allowed.
@Small_Header@<:#259,9360>Remarks
<:#2430,9360><+!>MONEY<-!> variables are stored as positive or negative cents. The range of
<+!>MONEY<-!> is $-21,474,836.48 through $+21,474,836.47. It is stored internally as a four byte signed long integer. If
<+!>MONEY<-!> is assigned to or from an <+!>INTEGER<-!> type then the cents (-2,147,483,648 - +2,147,483,647) are assigned. If
<+!>MONEY<-!> is assigned to a <+!>STRING<-!> type then it is automatically converted to the following format: "$sD.CC", where s is the sign (- for negative amounts, nothing for positive amounts), D is the dollar amount (one or more digits as needed) and C
C is the cents amount (00-99). If a <+!>STRING<-!></`>is assigned to
<+!>MONEY<-!> then PPL will do it's best to convert the string back to the appropriate amount of money. All other types, when assigned to or from
<+!>MONEY<-!>, will be converted to an <+!>INTEGER<-!> first before being assigned to or from the
<:#240,9360>Pause the display and ask the user how to continue.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>MORE<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1440,9360>It is often necessary to pause in the display of information and wait for the user to catch up. This statement allows you prompt the user on how to continue. The acceptable responses are Y (or whatever letter is appropriate for the users language selectio
n) to continue, N (or, again, whatever letter is appropriate) to abort, or NS to continue in non-stop mode. It displays prompt number 196 from the PCBTEXT file for the current language to let the user know what is expected.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#632,9360>PRINTLN "Your account has expired!"<**>PRINTLN "You are about to be logged off"<**><+!>MORE<-!><**>PRINTLN "Call me voice to renew your subscription"
@Indent_List@<:#240,9360> <:f,QCourier,>exp<:f> An expression of any type to evaluate and write to the caller's screen.
@Small_Header@<:#259,9360>Remarks
<:#1455,9360>These statements will evalutate zero, one or more expressions of any type and write the results to the modem for the caller's display. The
<+!>MPRINTLN<-!> statement will append a newline to the end of the expressions;
<+!>MPRINT<-!> will not. Note that at least one expression must be specified for
<+!>MPRINT<-!>, unlike the <+!>MPRINTLN<-!> statement which need not have any arguments passed to it. These statements only send information to the modem and do not interpret @ codes; if the remote caller has ANSI then ANSI will be interpreted.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#948,9360><+!>MPRINT "The name of the currently running PPE file is "<**>MPRINTLN PPENAME(),"."<**>MPRINT "The path where it is located is "<**>MPRINTLN PPEPATH(),"."<**>MPRINT "The date is ",DATE()," and the time is ",TIME(),"."<**>MPRINTLN<-!>
<:#485,9360>Set the new line after prompt flag in an <+!>INPUTSTR<-!>, <+!>PROMPTSTR<-!>, or
<+!>DISPTEXT<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>64 = 1000000b = 100o = 40h
@Small_Header@<:#259,9360>Remarks
<:#730,9360>The <+!>INPUTSTR<-!>, <+!>PROMPTSTR<-!>, and <+!>DISPTEXT<-!> statements have the ability to send a carriage return/line feed after a prompt is displayed automatically and without the need to make a separate call to the
<:#240,9360>Move the cursor to the beginning of the next line.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>NEWLINE<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#725,9360>This statement should be used for moving to the beginning of the next line on screen, scrolling if necessary. It will do so regardless of the current cursor position, unlike the
<+!>FRESHLINE<-!> statement.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>INTEGER i, end<**>LET end = RANDOM(20)<**>FOR i = 1 TO end<**> PRINT RIGHT(RANDOM(10000),8)<**>NEXT<**>FRESHLINE<+!><**>NEWLINE<-!><**>PRINTLN "Now we continue with a blank line between"
<:#245,9360>Execute a specified number of <+!>NEWLINE<-!> statements.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>NEWLINES count<:f>
@Indent_List@<:#245,9360> <:f,QCourier,>count<:f> An integer expression with the number of times to execute
<+!>NEWLINE<-!>.
@Small_Header@<:#259,9360>Remarks
<:#975,9360>This statement is convienient when executing multiple and/or variable
<+!>NEWLINE<-!> statements for screen formatting. It takes a single integer expression argument and automatically executes that many
<+!>NEWLINE<-!> statements for you without the need to set up a loop or to write multiple
<+!>NEWLINE<-!> lines in your source code.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>INTEGER i, end<**>LET end = RANDOM(20)<**>FOR i = 1 TO end<**> PRINT RIGHT(RANDOM(10000),8)<**>NEXT<**>FRESHLINE<+!><**>NEWLINE 5<-!><**>PRINTLN "Now we continue with a 5 blank lines between"
<:#240,9360>Change the users password and maintain the password PSA if installed.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>NEWPWD pwd,var<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>pwd<:f> A string expression with the new password for the user.
@Indent_List@<:#490,9360> <:f,QCourier,>var<:f> A variable to hold the password change status;
<+!>TRUE<-!> if the password was changed or <+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#2180,9360>There are two ways to change the users password under PPL control. The first is to simply use the
<+!>GETUSER<-!> statement, assign the new password to the <+!>U_PWD<-!> variable, then issue the
<+!>PUTUSER<-!> statement. However, this isn't adequate if the SysOp has installed the password PSA. This statement will take care of validating the password, checking it against the password history, updating the password history, setting a new expiratio
n date if necessary and incrementing the times changed counter. If the password fails a validity test then this statement will set the var parameter to
<+!>FALSE<-!> to let you know that the password wasn't changed. If the password PSA isn't installed or if the password conforms to the PSA requirements, then var will be set to
<+!>TRUE<-!>.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#948,9360>BOOLEAN changed<**>STRING pwd<**>INPUTSTR "Enter a new password",pwd,@X0E,12,MASK_PWD(),ECHODOTS<**>NEWLINE<+!><**>NEWPWD pwd,changed<-!><**>IF (!changed) PRINTLN "Password not changed"
@Small_Header@<:#259,9360>See Also
<:#240,9360><-">
<:p<* >>
@Subhead@<:#360,9360>NOCHAR() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Get the no response character for the current language.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the no character for the current language.
@Small_Header@<:#259,9360>Remarks
<:#480,9360>Support for foreign language yes/no responses can be easily added by using this function to determine what a negative response should be instead of hardcoding the english "N" character.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>STRING ans<**>LET ans = YESCHAR()<**>INPUTSTR "Run program now",ans,@X0E,1,"",AUTO+YESNO<**>IF (ans =
<:#245,9360>Set the no clear input field flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>1024 = 10000000000b = 2000o = 400h
@Small_Header@<:#259,9360>Remarks
<+C><:#965,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to automatically clear the default value from the input field when the users presses his first key if ANSI is available. This is the default mode of operations. If you don't want this
to happen, you may use this flag to disable this feature.
<:#240,9360>Calculate the bitwise NOT of an integer argument.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>NOT(iexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>iexp<:f> Any integer expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the bitwise NOT of iexp.
@Small_Header@<:#259,9360>Remarks
<:#480,9360>This function may be used to toggle all bits in an integer expression. Wherever a bit had been set it will be clear after this function call, and vice versa.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#810,9360>' Toggle the bits<**>PRINTLN <+!>NOT(1248h)<-!><**>' Toggle all flag<**>INTEGER flag<**>LET flag =
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if the caller is on locally,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>There are some features that work differently for local and remote callers, such as file transfers and modem communications. This function will report to you whether or not a user is logged on locally and allow you to handle local processing differently th
an remote processing.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>IF (<+!>ONLOCAL()<-!>) THEN<**> PRINTLN "Call back verification cannot be performed for"<**> PRINTLN "users logged in locally!"<**> END<**>ENDIF<**>CALL "CALLBACK.PPE"
@Indent_List@<:#240,9360> <:f,QCourier,>file<:f> A string expression with the filename to open.
@Indent_List@<:#485,9360> <:f,QCourier,>stat<:f> A variable to hold the return status (<+!>TRUE<-!> if error opening file,
<+!>FALSE<-!> otherwise).
@Small_Header@<:#259,9360>Remarks
<:#2185,9360>PCBoard has the ability to capture screen output to a file for later reference. PPL allows that same ability via the
<+!>OPENCAP<-!> and <+!>CLOSECAP<-!> statements. This could be useful in a program that executes a series of commands in non-stop mode. The process could open a capture file first, execute the commands, close the capture file, then allow the user to view
or download the capture file. <+!>CLOSECAP<-!> closes the capture file and turns off screen capturing. Also, the
<+!>SHOWON<-!> and <+!>SHOWOFF<-!> statements can be used to turn on and off showing information to the screen while allowing that same information (even if not displayed or transmitted via modem) to be captured to a file. The
<+!>SHOWSTAT()<-!> function can be used to check the current status of the
<+!>SHOWON<-!> and <+!>SHOWOFF<-!></`>statements.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2212,9360>BOOLEAN ss<**>LET ss = SHOWSTAT()<**>SHOWOFF<+!><**>OPENCAP "CAP"+STRING(PCBNODE()),ocFlag<-!><**>IF (ocFlag) THEN<**> DIR "U;NS"<**> CLOSECAP<**> KBDSTUFF "FLAG CAP"+STRING(PCBNODE())+CHR(13)<**>ENDIF<**>IF (ss) THEN<**> SHOWON<**>ELSE<**> SHOWOFF<**>
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>The @OPTEXT@ macro is used to include operation specific text in prompts and display files. Normally PCBoard automatically fills it in with the appropriate value. However, you can use it for your own purposes by issuing this statement to set the text and
immediately displaying the information that should use it (by either printing a line or displaying a file).
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#474,9360><+!>OPTEXT STRING(DATE())+" & "+STRING(TIME())<-!><**>PRINTLN "The date and time are @OPTEXT@"<**>DISPFILE "FILE",GRAPH+SEC+LANG
@Small_Header@<:#259,9360>See Also
<:#240,9360><-">
<:p<* >>
@Subhead@<:#360,9360>OR() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Calculate the bitwise OR of two integer arguments.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>OR(iexp1,iexp2)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>iexp1<:f> Any integer expression.
@Indent_List@<:#240,9360> <:f,QCourier,>iexp2<:f> Any integer expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the bitwise OR of iexp1 and iexp2.
@Small_Header@<:#259,9360>Remarks
<:#480,9360>This function may be used to set selected bits in an integer expression by ORing the expression with a mask that has the bits to set set to 1 and the bits to ignore set to 0.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#810,9360>' Set the bits in the low byte<**>PRINTLN <+!>OR(1248h,00FFh)<-!><**>' Randomly set a flag the hard way<**>INTEGER flag<**>LET flag =
<:#245,9360>Set the open for read access flag in a <+!>FCREATE<-!>/<+!>FOPEN<-!>/<+!>FAPPEND<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>0 = 0b = 0o = 0h
@Small_Header@<:#259,9360>Remarks
<:#960,9360>Files may be opened for read, write or combined read/write access. You should only use the access you need to allow other processes to open files at the same time in multitasking and networked environments. This constant will allow your PPE to read from a
file without writing any information out to it.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>FOPEN 1,"FILE.DAT",<+!>O_RD<-!>,S_DN ' Open for read access<**>FOR i = 1 TO 10<**> FGET 1,s<**> PRINTLN s<**>NEXT<**>FCLOSE 1
<:#245,9360>Set the open for read and write access flag in a <+!>FCREATE<-!>/<+!>FOPEN<-!>/<+!>FAPPEND<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>2 = 10b = 2o = 2h
@Small_Header@<:#259,9360>Remarks
<:#960,9360>Files may be opened for read, write or combined read/write access. You should only use the access you need to allow other processes to open files at the same time in multitasking and networked environments. This constant will allow your PPE to both read f
rom and write to a file without the need to close and reopen it between accesses.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>FOPEN 1,"FILE.DAT",<+!>O_RW<-!>,S_DN ' Open for read and write access<**>FOR i = 1 TO 10<**> FPUT 1,"X"<**> FGET 1,s<**> PRINTLN s<**>NEXT<**>FCLOSE 1
<:#245,9360>Set the open for write access flag in a <+!>FCREATE<-!>/<+!>FOPEN<-!>/<+!>FAPPEND<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>1 = 1b = 1o = 1h
@Small_Header@<:#259,9360>Remarks
<:#960,9360>Files may be opened for read, write or combined read/write access. You should only use the access you need to allow other processes to open files at the same time in multitasking and networked environments. This constant will allow your PPE to write to a
file but will restrict read access.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#800,9360>FOPEN 1,"FILE.DAT",<+!>O_WR<-!>,S_DN ' Open for write access<**>FOR i = 1 TO 10<**> FPUTLN 1,"Line ",i<**>NEXT<**>FCLOSE 1
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>One of the features of PCBoard where change is often requested is the operator page facility. Some people want to be able to configure multiple ranges of availability per day, some want a different sounding page bell, longer or shorter page attempts, etc,
etc. This statement, along with the <+!>CHAT<-!> and <+!>PAGEON<-!> statements and the
<+!>PAGESTAT()<-!> function, allow you to implement an operator page in any way desired.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1748,9360>PAGEON<**>FOR i = 1 TO 10<**> PRINT "@BEEP@"<**> DELAY 18<**> IF (KINKEY() = " ") THEN<**>
<:#240,9360>Turn on the SysOp paged indicator and update user statistics.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>PAGEON<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1445,9360>One of the features of PCBoard where change is often requested is the operator page facility. Some people want to be able to configure multiple ranges of availability per day, some want a different sounding page bell, longer or shorter page attempts, etc,
etc. This statement, along with the <+!>CHAT<-!> and <+!>PAGEOFF<-!> statements and the
<+!>PAGESTAT()<-!> function, allow you to implement an operator page in any way desired. Note that this statement will also update the current callers statistics PSA if it is installed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1580,9360><+!>PAGEON<-!><**>FOR i = 1 TO 10<**> PRINT "@BEEP@"<**> DELAY 18<**> IF (KINKEY() = " ") THEN<**> CHAT<**> GOTO exit<**> ENDIF<**>NEXT<**>:exit
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if the user has paged the SysOp,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>One of the features of PCBoard where change is often requested is the operator page facility. Some people want to be able to configure multiple ranges of availability per day, some want a different sounding page bell, longer or shorter page attempts, etc,
etc. This function, along with the <+!>CHAT<-!>, <+!>PAGEON<-!> and
<+!>PAGEOFF<-!> statements, allow you to implement an operator page in any way desired.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>IF (<+!>PAGESTAT()<-!>) THEN<**> PRINTLN "You have already paged the SysOp,"<**> PRINTLN "please be patient."<**>ELSE<**> PAGEON<**> PRINTLN "The SysOp has been paged, continue"<**>ENDIF
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns the path and file name of the PCBOARD.DAT file for the currnet node.
@Small_Header@<:#259,9360>Remarks
<:#965,9360>The PCBOARD.DAT file is the master confiuration file for each node running PCBoard. As such, there are many useful pieces of information that can be obtained from it. It is a standard text file with one piece of information per line. You may use the
<+!>READLINE()<-!> function to read individual pieces of information from it.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#484,9360>STRING s<**>LET s = READLINE(<+!>PCBDAT()<-!>,1)<**>PRINTLN "PCBOARD.DAT version info - ",s
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the node number for the current node.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>You may have need to know what node is in use for certain applications (for example, to create temporary files with unique names or to restrict features to a particular node or nodes). This function will return a number from 1 to the maximum number of node
s allowed with a given copy of PCBoard. Note that the node number may not be what is defined in PCBOARD.DAT if the /FLOAT or /NODE switches are used.
<:#240,9360>Return the value of a byte at a specified memory address.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>PEEKB(addr)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>addr<:f> An integer expression with the address of the byte to peek.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the value of the byte at addr.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>It is sometimes necessary to read values from memory directly (for example, from the system BIOS data segment). This function will return a byte quantity (0-255) from a specified memory address.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "The current video mode is ",<+!>PEEKB(MKADDR(40h,49h))<-!>
<:#240,9360>Return the value of a double word at a specified memory address.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>PEEKDW(addr)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>addr<:f> An integer expression with the address of the double word to peek.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the value of the double word at addr.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>It is sometimes necessary to read values from memory directly (for example, from the system BIOS data segment). This function will return a double word quantity as a signed integer (-2,147,483,648 - +2,147,483,647) from a specified memory address.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "Timer ticks since midnight = ",<+!>PEEKDW(MKADDR(40h,6Ch))<-!>
<:#240,9360>Return the value of a word at a specified memory address.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>PEEKW(addr)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>addr<:f> An integer expression with the address of the word to peek.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the value of the word at addr.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>It is sometimes necessary to read values from memory directly (for example, from the system BIOS data segment). This function will return a word quantity (0-65,535) from a specified memory address.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "The usable memory size is ",<+!>PEEKW(MKADDR(40h,13h))<-!>
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> A variable of any type in which to retrieve previously pushed expression.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>This statement will retrieve the results of one or more expressions of any type from a stack into a list of variables. The values should have been previously pushed with the
<+!>PUSH<-!> statement. Together <+!>PUSH<-!> and <+!>POP<-!> can be used for parameter passing, to create 'local' variables, or to reverse the order of arguments.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#5412,9360>INTEGER i, tc<**>STRING s<**>LET tc = TOKCOUNT()<**>WHILE (TOKCOUNT() <;> 0) PUSH GETTOKEN() ' push them in order<**>FOR i = 1 TO tc<**>
<+!>POP s<-!> ' pop them in reverse<**> PRINTLN s<**>NEXT<**><**>INTEGER i<**>FOR i = 1 TO 10<**> PRINT i," - "<**> GOSUB sub<**>NEXT<**>END<**>:sub<**>PUSH i ' temporarily save i<**>LET i =
i*i<**>PRINTLN i<**><+!>POP i<-!> ' restore saved i<**>RETURN<**><**>INTEGER v<**>PRINT "A cube with dimensions 2X3X4"<**>PUSH 2,3,4 ' pass pushed parameters<**>GOSUB vol<+!><**>POP v<-!>
' pop result<**>PRINTLN "has volume ",v<**>END<**>:vol<**>INTEGER w,h,d<**><+!>POP d,h,w<-!> ' pop passed parameter<**>PUSH w*h*d ' push result<**>RETURN
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns the base file name (without path or extension) of the currently executing PPE.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function will return the name of the PPE file that is running. This can be useful when writing PPL applications that will use data files that you would like to keep named the same as the parent application regardless of what the PPE name may change to
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns the path (without file name or extension) of the currently executing PPE.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function will return the path of the PPE file that is running. This can be useful when writing PPL applications that will use files that you would like to keep in the same location as the parent application regardless of where the PPE may be installed
@Indent_List@<:#240,9360> <:f,QCourier,>exp<:f> An expression of any type to evaluate and write to the screen.
@Small_Header@<:#259,9360>Remarks
<:#1215,9360>These statements will evalutate zero, one or more expressions of any type and write the results to the display. The
<+!>PRINTLN<-!> statement will append a newline to the end of the expressions;
<+!>PRINT<-!> will not. Note that at least one expression must be specified for
<+!>PRINT<-!>, unlike the <+!>PRINTLN<-!> statement which need not have any arguments passed to it. Finally, both statements will process all @ codes and display them as expected.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360><+!>PRINT "The name of the currently running PPE file is "<**>PRINTLN PPENAME(),"."<**>PRINT "The path where it is located is "<**>PRINTLN PPEPATH(),"."<**>PRINT "The date is ",DATE()," and the time is ",TIME(),"."<**>PRINTLN<**>PRINT "@X1FThis is bright wh
ite on blue..."<**>PRINTLN "how do you like it @FIRST@"<-!>
@Indent_List@<:#480,9360> <:f,QCourier,>prompt<:f> An integer expression with the prompt number from PCBTEXT to display to the user.
@Indent_List@<:#240,9360> <:f,QCourier,>var<:f> The variable in which to store the user's input.
@Indent_List@<:#240,9360> <:f,QCourier,>len<:f> An integer expression with maximum length of text to input.
@Indent_List@<:#240,9360> <:f,QCourier,>valid<:f> A string expression with the valid characters that the user may enter.
@Indent_List@<:#240,9360> <:f,QCourier,>flags<:f> An integer expression with flags to modify how the statement works.
@Small_Header@<:#259,9360>Remarks
<:#2425,9360>This statement will accept a string of input from the user, up to the length defined. The prompt parameter will be used to find the prompt from PCBTEXT (which includes the prompt color) to display to the user. Only characters found in the valid parameter
will be accepted. However, the flags parameter may affect how prompt is displayed and the valid characters that are accepted. Individual flags may be added together as needed. Several functions exist to easily specify commonly used valid character masks.
They are <+!>MASK_ALNUM()<-!>, <+!>MASK_ALPHA()<-!>, <+!>MASK_ASCII()<-!>,
<+!>MASK_FILE()<-!>, <+!>MASK_NUM()<-!>, <+!>MASK_PATH()<-!>, and
<+!>MASK_PWD()<-!>. Defined flag values are <+!>AUTO<-!>, <+!>DEFS<-!>,
<+!>NOCLEAR<-!>, <+!>STACKED<-!>, <+!>UPCASE<-!>, <+!>WORDWRAP<-!>, and
<+!>YESNO<-!>.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2528,9360>BOOLEAN b<**>DATE d<**>INTEGER i<**>MONEY m<**>STRING s<**>TIME t<**>' NOTE: prompt 706 is used here for all statements;<**>' you may use any prompt you wish<+!><**>PROMPT<-!><+!>STR<-!><+!> 706<-!><+!>,b,1,"10",LFBEFORE+NEWLINE<**>PROMPT<-!>
@Indent_List@<:#480,9360> <:f,QCourier,>num<:f> An integer expression with the number of the PSA to check for the existence of.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!></`>if the specified PSA exists or
<+!>FALSE<-!> if it doesn't exist for the following values of num:
@Indent_List@<:#240,9360> 1 The Alias PSA;
@Indent_List@<:#240,9360> 2 The Verification PSA.
@Indent_List@<:#240,9360> 3 The Address PSA;
@Indent_List@<:#240,9360> 4 The Password PSA;
@Indent_List@<:#240,9360> 5 The Statistics PSA.
@Indent_List@<:#240,9360> 6 The Notes PSA.
@Small_Header@<:#259,9360>Remarks
<:#965,9360>This function allows you to determine whether or not a given PCBoard Supported Allocation (PSA) is installed. For each of the six PSAs it will return
<+!>TRUE<-!> if installed or <+!>FALSE<-!> if not installed. It is useful when you want to write a generic PPL application that will access one or more PSAs that may or may not be installed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1482,9360>STRING ynStr(1)<**>LET ynStr(0) = "NO"<**>LET ynStr(1) = "YES"<**>PRINTLN " Alias Support Enabled? ",ynStr(<+!>PSA(1)<-!>)<**>PRINTLN "Verification Support Enabled? ",ynStr(<+!>PSA(2)<-!>)<**>PRINTLN " Address Support Enabled? ",ynStr(<+!>PSA(3
)<-!>)<**>PRINTLN " Password Support Enabled? ",ynStr(<+!>PSA(4)<-!>)<**>PRINTLN " Statistics Support Enabled? ",ynStr(<+!>PSA(5)<-!>)<**>PRINTLN " Notes Support Enabled? ",ynStr(<+!>PSA(6)<-!>)
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>PUSH <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Push (save) the results of one or more expressions on a stack.
@Indent_List@<:#240,9360> <:f,QCourier,>exp<:f> An expression of any type to evaluate and push.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>This statement will evalutate one or more expressions of any type and push the results onto a stack for temporary storage. The results of those expressions may be retrieved via the
<+!>POP<-!> statement. Together <+!>PUSH<-!> and <+!>POP<-!> can be used for parameter passing, to create 'local' variables, or to reverse the order of arguments.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#5412,9360>INTEGER i, tc<**>STRING s<**>LET tc = TOKCOUNT()<**>WHILE (TOKCOUNT() <;> 0)
<+!>PUSH GETTOKEN()<-!> ' push them in order<**>FOR i = 1 TO tc<**> POP s ' pop them in reverse<**> PRINTLN s<**>NEXT<**><**>INTEGER i<**>FOR i = 1 TO 10<**> PRINT i," - "<**> GOSUB sub<**>NEXT<**>END<**>:sub<+!><**>PUSH i
<-!> ' temporarily save i<**>LET i = i*i<**>PRINTLN i<**>POP i ' restore saved i<**>RETURN<**><**>INTEGER v<**>PRINT "A cube with dimensions 2X3X4"<+!><**>PUSH 2,3,4<-!>
' pass pushed parameters<**>GOSUB vol<**>POP v ' pop result<**>PRINTLN "has volume ",v<**>END<**>:vol<**>INTEGER w,h,d<**>POP d,h,w ' pop passed parameter<**><+!>PUSH w*h*d<-!>
<:#240,9360>Copy values from predeclared variables to user record.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>PUTUSER<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#730,9360>There are many predeclared variables which may be used to access and change user information. However, their values are undefined until you use the
<+!>GETUSER<-!> statement, and any changes you make don't take hold until you use the
<:#240,9360>Allow the user to answer a specified script questionnaire.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>QUEST scrnum<:f>
@Indent_List@<:#480,9360> <:f,QCourier,>scrnum<:f> The number of the script for the user to answer. Valid values are 1 through the number of script questionnaires available.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This statement will present the user a specified script questionnaire number to answer. The SCR.LST file for the current conference will be searched for the script. If the questionnaire number is invalid (less than 1 or greater than the highest script num
ber defined) then nothing will be displayed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#474,9360>INTEGER num<**>INPUT "Script to answer",num<+!><**>QUEST num<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360>
<:p<* >>
@Subhead@<:#360,9360>RANDOM() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Return a random value between 0 and a specified limit.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>RANDOM(limit)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>limit<:f> An integer expression with the maximum random value desired.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the random number in the range 0 to limit.
@Small_Header@<:#259,9360>Remarks
<:#480,9360>Random numbers have many applications from statistics to video games. This function allows you to generate pseudo-random numbers in the range 0 to limit inclusive.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1926,9360>INTEGER x,y<**>WHILE (KINKEY() <<<;> " ") DO<**> CLS<**> LET x = 1+<+!>RANDOM(50)<-!><**> LET y = 1+<+!>RANDOM(22)<-!><**> COLOR 1+<+!>RANDOM(14)<-!><**> ANSIPOS x,y<**> PRINT "Hit the SPACE BAR to continue"<**> DELAY 18<**> ANSIPOS x,y<**> CLREOL<**>
ENDWHILE
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-"><-"><-"><-"><-">
<:p<* >>
@Subhead@<+@><:#360,9360>RDUNET <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Read information from the USERNET file for a specific node.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>RDUNET node<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>node<:f> An integer expression with the node to read.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>To facilitate internode communications, a file named USERNET.XXX is maintained with an entry for each node on the system. This file is used by the BROADCAST command of PCBoard and to prevent multiple simultaneous logins, among other things. This statement
may be used to read information for any node.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#632,9360><+!>RDUNET PCBNODE()<-!><**>WRUNET PCBNODE(),UN_STAT(),UN_NAME(),UN_CITY(),"Running "+PPENAME(),""<+!><**>RDUNET 1<-!><**>WRUNET 1,UN_STAT(),UN_NAME(),UN_CITY(),UN_OPER(),"Hello there node 1"
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#970,9360>Some DOOR applications require a USERS.SYS file to access information about the caller. This statement allows you to read the USERS.SYS file back into memory in case any changes were made by the DOOR during the
<+!>SHELL<-!> statement. This statement should only be used after a
<+!>SHELL<-!> statement that was preceeded by a <+!>WRUSYS<-!> statement.
@Indent_List@<:#240,9360> <:f,QCourier,>file<:f> A string expression with the file name to read from.
@Indent_List@<:#240,9360> <:f,QCourier,>line<:f> An integer expression with the line number to read.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the specified line number from file.
@Small_Header@<:#259,9360>Remarks
<:#1680,9360>It is often convienient to read a specified line number from a file without going to all the overhead of opening, reading and closing. This function will open the file in read mode for share deny none access and quickly read up to the line number you speci
fy. If the line you want doesn't exist an empty string will be returned. Additionally, this function will remember the last file and line read so that it may quickly continue where it left off if you try to read a number of lines sequentially from the sam
e file. Finally, the last file specified will remain open until the PPE exits and returns control to PCBoard.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#336,9360>PRINTLN "This system is running on IRQ ",<+!>READLINE(PCBDAT(),158)<-!><**>PRINTLN "with a base IO address of ",<+!>READLINE(PCBDAT(),159)<-!>
@Indent_List@<:#240,9360> No arguments are required
<:#480,9360>REG should be followed by one of the following register names: AH, AL, AX, BH, BL, BX, CF, CH, CL, CX, DH, DI, DL, DS, DX, ES, F or SI.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> (<+!>REGCF()<-!> only) Returns <+!>TRUE<-!> if the carry flag is set,
<+!>FALSE<-!> otherwise.
@Indent_List@<:#245,9360><+!>INTEGER<-!> (All others) Returns the value in the specified register.
@Small_Header@<:#259,9360>Remarks
<:#1930,9360>There are actually 18 different functions that return the values of registers. AL, AH, BL, BH, CL, CH, DL, and DH will always return byte sized values (0-255). AX, BX, CX, DX, DI, SI, DS, and ES will always return word sized values (0-65535). F (flags) r
eturns the settings for the various 80x86 processor flags. CF is a subset of F in that it only returns the status of the carry flag. It exists because the carry flag is often used to report success or failure in assembly language. The
<+!>REGF()<-!> function returns the settings for the following flags:
@Indent_List@<:#240,9360> <:f,QCourier,>old<:f> A string expression with the old path and/or file name.
@Indent_List@<:#240,9360> <:f,QCourier,>new<:f> A string expression with the new path and/or file name.
@Small_Header@<:#259,9360>Remarks
<:#1685,9360>Similar to how the RENAME command works from the DOS prompt, this statement will take a file and give it a new name. Unlike the RENAME command, the
<+!>RENAME<-!> statement will not accept wildcards in the old or new parameters. Also, it doesn't require that the old path and the new path be the same (the drive letters must match, but the paths need not), so it may be used to move files from one locati
on to another on a single drive. So, you could use it to move a file from C:\PCB\NODE1 to C:\PCB\NODE2 (renaming it at the same time if you wish), but you couldn't use it to move a file from C:\PCB\NODE1 to D:\WORK\NODE1.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1106,9360>' Swap the PCBOARD DAT & NXT files<+!><**>RENAME "PCBOARD.DAT","PCBOARD.TMP"<**>RENAME "PCBOARD.NXT","PCBOARD.DAT"<**>RENAME "PCBOARD.TMP","PCBOARD.NXT"<**><-!><**>' Move the file to the backup directory<+!><**>RENAME "PPE.LOG","LOGBAK\"+I2S(DATE()*86400+TI
ME(),36)<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360><-">
<:p<* >>
@Subhead@<:#360,9360>REPLACE() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Change all occurences of a given character to another character in a string.
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression.
@Indent_List@<:#240,9360> <:f,QCourier,>old<:f> A string expression with the old character to be replaced.
@Indent_List@<:#240,9360> <:f,QCourier,>new<:f> A string expression with the new character to replace with.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns str with all occurences of old changed to new.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function will search a string for a given character and replace all instances of that character with another character. This can be useful in many scenarios, especially when formatting text for display purposes.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#326,9360>PRINTLN "Your internet address on this system is:"<**>PRINTLN <+!>REPLACE(LOWER(U_NAME())," ",".")<-!>,"@clarkdev.com"
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-"><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>RESETDISP <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Reset the display to allow more information after an abort.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>RESETDISP<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1210,9360>PCBoard normally automatically counts lines and, if enabled, pauses the display after every screenful. The user may (unless disabled) abort the display at any
<:f,QCourier,>MORE?<:f> prompt or with the ^K/^X keys. If this happens no further information will be displayed until you use the
<+!>RESETDISP<-!> statement. You can check to see if <+!>RESETDISP<-!> is necessary (ie, has the user aborted the display) with the
<+!>ABORT()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>INTEGER I<**>STARTDISP FCL<**>' While the user has not aborted, continue<**>WHILE (!ABORT()) DO<**> PRINTLN "I is equal to ",I<**> INC I<**>ENDWHILE<+!><**>RESETDISP<-!>
<:#240,9360>Restore the screen from a previously saved buffer.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>RESTSCRN<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remark
<:#2175,9360>PCBoard will save and restore the screen before and after certain functions, such as SysOp chat. This allows the user to continue right where he left off without having to remember what was on the screen before being interrupted. You can add that same fun
ctionality with the <+!>SAVESCRN<-!> and <+!>RESTSCRN<-!> statements. The
<+!>SAVESCRN<-!> statement allocates memory for a buffer in which to save the screen. If the
<+!>SAVESCRN<-!> statement isn't followed by a <+!>RESTSCRN<-!> statement then that memory will never be deallocated. Finally, this statement will work regardless of ANSI availability; the screen is only saved up to the position of the cursor and this stat
ement assumes that it can safely restore the screen using standard teletype conventions to just scroll the data onto the display.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1580,9360>SAVESCRN<**>CLS<**>PRINTLN "We interrupt your regular BBS session"<**>PRINTLN "with this important message:"<**>NEWLINE<**>PRINTLN "A subscription to this system only costs $5!"<**>PRINTLN "Subscribe today!"<**>NEWLINES 2<**>WAIT<+!><**>RESTSCRN<-!>
<:#240,9360>Transfer program control back to a previously saved address.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>RETURN<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1215,9360>It is often necessary to perform an indentical set of instructions several times in a program. This leaves you with two choices. One, rewrite the code several times (and hope you do it right each time), or two, write it once as a subroutine, then use
<+!>GOSUB<-!> to run it. This statement will save the address of the next line so that a
<+!>RETURN<-!> statement at the end of the subroutine can instruct PPL to resume execution with the line following the
<+!>GOSUB<-!>.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2370,9360>STRING Question, Answer<**>LET Question = "What is your street address ..."<**>GOSUB ask<**>LET Question = "What is your city, state and zip ..."<**>GOSUB ask<**>END<**><**>:ask ' Sub to ask a question, get an answer, and log them to a file<**>LET Answer =
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> A string expression to take the right most characters of.
@Indent_List@<:#480,9360> <:f,QCourier,>chars<:f> An integer expression with the number of characters to take from the right end of str.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns a string with the right most chars characters of str.
@Small_Header@<:#259,9360>Remarks
<:#960,9360>This function will return a sub string with the right most chars characters of a specified string. This can be useful in data processing as well as text formatting. If chars is less than or equal to 0 then the returned string will be empty. If chars is g
reater than the length of str then the returned string will have spaces added to the right to pad it out to the full length specified.
<:#240,9360>Trim a specified character from the right end of a string.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>RTRIM(str,ch)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression.
@Indent_List@<:#240,9360> <:f,QCourier,>ch<:f> A string with the character to strip from the right end of str.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the trimmed str.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>A common need in programming is to strip leading and/or trailing spaces (or other characters). This function will strip a specified character from the right end of a string and return the trimmed string.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#820,9360>STRING s<**>LET s = " TEST "<**>PRINTLN <+!>RTRIM(s," ")<-!> ' Will print " TEST"<**>PRINTLN
<+!>RTRIM(".....DA"+"TA.....",".")<-!> ' Will print ".....DATA"<**>PRINTLN
<+!>RTRIM(".....DA"+"TA....."," ")<-!> ' Will print ".....DATA....."
<:#240,9360>Convert a string in a specified number base to an integer.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>S2I(str,base)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression to convert to integer format.
@Indent_List@<:#480,9360> <:f,QCourier,>base<:f> An integer expression with the number base (2 through 36) to convert from.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns str converted from the specified number base to an integer.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>People work with decimal (base 10) numbers, whereas computers work with binary (base 2) numbers. It is often more convienient to store or input numbers in a format other than decimal for clarity, compactness, or other reasons. This function will convert a
string in any number base from 2 to 36 to a number. So, <+!>S2I("1010",2)<-!> would return a 10;
<+!>S2I("Z",36)<-!> would return 35. For more information on number bases, consult
<:N737425047,SDR,65535,4,1
Reference number base theory
>
.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>INTEGER i<**>STRING s<**>INPUTTEXT "Enter a string (any base)",s,@X0E,40<**>FOR i = 2 TO 36<**> PRINTLN s," = ",<+!>S2I(s,i)<-!>," base ",i<**>NEXT
<:#240,9360>Save the screen to a buffer for later restoration.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>SAVESCRN<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remark
<:#2175,9360>PCBoard will save and restore the screen before and after certain functions, such as SysOp chat. This allows the user to continue right where he left off without having to remember what was on the screen before being interrupted. You can add that same fun
ctionality with the <+!>SAVESCRN<-!> and <+!>RESTSCRN<-!> statements. The
<+!>SAVESCRN<-!> statement allocates memory for a buffer in which to save the screen. If the
<+!>SAVESCRN<-!> statement isn't followed by a <+!>RESTSCRN<-!> statement then that memory will never be deallocated. Finally, this statement will work regardless of ANSI availability; this statement will only save the screen up to the position of the curs
or. It is assumed that the screen can be safely restored using standard teletype conventions to just scroll the data onto the display.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1580,9360><+!>SAVESCRN<-!><**>CLS<**>PRINTLN "We interrupt your regular BBS session"<**>PRINTLN "with this important message:"<**>NEWLINE<**>PRINTLN "A subscription to this system only costs $5!"<**>PRINTLN "Subscribe today!"<**>NEWLINES 2<**>WAIT<**>RESTSCRN
@Indent_List@<:#480,9360> <:f,QCourier,>x<:f> An integer expression with the x coordinate (column) from which to read screen memory.
@Indent_List@<:#480,9360> <:f,QCourier,>y<:f> An integer expression with the y coordinate (row) from which to read screen memory.
@Indent_List@<:#480,9360> <:f,QCourier,>len<:f> An integer expression with the length, in columns, of the string to read from screen memory.
@Indent_List@<:#490,9360> <:f,QCourier,>color<:f> A boolean expression with <+!>TRUE<-!> if color information should be included,
<+!>FALSE<-!> otherwise.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the specified region of screen memory.
@Small_Header@<:#259,9360>Remarks
<:#1685,9360>This function is useful for temporarily saving a portion of screen memory, with or without color information. If the color parameter is set to
<+!>TRUE<-!> color information will be included in the form of @X codes embedded in the text. Note that the maximum length of a string is 256 characters; however, a row of 80 characters could be as long as 400 characters (4 bytes for the @X code and 1 byte
for the character itself). You should generally limit yourself to a length of 51 characters or less if you want to include color information unless you are certain that attribute changes will not exceed the 256 character string limit.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2064,9360>' scroll the screen to the left 5 columns and down 3 rows<**>INTEGER r<**>STRING s<**>FOR r = 20 TO 1 STEP -1<**> LET s =
<+!>SCRTEXT(6,r,75,TRUE)<-!><**> ANSIPOS 1,r+3<**> CLREOL<**> PRINT s<**>NEXT<**>FOR r = 1 TO 3<**> ANSIPOS 1,r<**> CLREOL<**>NEXT
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-"><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>SEC <+">Constant<-">
@Small_Header@<:#259,9360>Function
<:#245,9360>Set the security level specific file search flag in a <+!>DISPFILE
<-!>statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>2 = 10b = 2o = 2h
@Small_Header@<:#259,9360>Remarks
<:#970,9360>The <+!>DISPFILE<-!> statement will allow you to display a file to the user, and optionally to have PCBoard look for alternate security, graphics, and/or language specific files. This flag instructs PCBoard to search for alternate security level files via
the security level suffix. The current security level may be obtained with the
<+">Function<-">, <-!><+!>DISPFILE <+">Statement<-">, GRAPH <+">Constant<-">, LANG
<+">Constant<-"><-!><-">
<:p<* >>
@Subhead@<:#360,9360>SEC() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Extract the second of the minute from a specified time of day.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>SEC(texp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>texp<:f> Any time expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns the second of the minute from the specified time expression (texp). Valid return values are from 0 to 59.
@Small_Header@<:#259,9360>Remarks
<:#485,9360>This function allows you to extract a particular piece of information about a
<+!>TIME<-!> value, in this case the second of the minute of the time of day expression.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "The minute is ",<+!>SEC(TIME())<-!>
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> A string expression to send to the modem.
@Small_Header@<:#259,9360>Remarks
<:#1440,9360>The primary use of this statement is to send commands to a modem when no one is online. For example, you would use this to send a dial command to the modem in a call back PPL application. However, it is not restricted to sending commands. Note that modem
commands must be terminated by a carriage return and that this statement will not automatically do it for you. This allows you to send a command to the modem is several stages and only terminate the final stage with a carriage return.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2054,9360>BOOLEAN flag<**>CDCHKOFF<**>KBDCHKOFF<**>DTROFF<**>DELAY 18<**>DTRON<+!><**>SENDMODEM "ATDT"<**>SENDMODEM "5551212"<**>SENDMODEM CHR(13)<-!><**>WAITFOR "CONNECT",flag,60<**>IF (!flag) LOG "No CONNECT after 60 seconds",FALSE<**>KBDCHKON<**>CDCHKON
@Indent_List@<:#490,9360> <:f,QCourier,>viacc<:f> A boolean expression with value <+!>TRUE<-!> if the shell should be made via COMMAND.COM;
<+!>FALSE<-!> if it should be shelled to directly.
@Indent_List@<:#240,9360> <:f,QCourier,>retcode<:f> A variable in which to store the return code.
@Indent_List@<:#240,9360> <:f,QCourier,>prog<:f> A string expression with the file name to shell to.
@Indent_List@<:#240,9360> <:f,QCourier,>cmds<:f> A string expression with any arguments to pass to prog.
@Small_Header@<:#259,9360>Remarks
<:#1935,9360>You may have have need to run a COM, EXE or BAT file from your PPE. You may need to do this to simulate running a DOOR or to access some service not normally available from PCBoard or PPL. This function will allow you to do that. If the viacc parameter i
s <+!>TRUE<-!> (you want COMMAND.COM to load the specified file) then your PATH environment variable will be searched for prog if it isn't in the current directory or isn't fully qualified (path and extension) as though you had entered it on the command lin
e. If viacc is <+!>FALSE<-!> then you must specify the path and extension of the program to run. Additionally, the retcode variable will only be meaningful if viacc is
<+!>FALSE<-!>.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1264,9360>INTEGER rc<+!><**>SHELL TRUE,rc,"DOOR",""<-!><**><**>INTEGER rc<**>STRING p,c<**>LET p = "DOORWAY.EXE"<**>LET c = "com2 /v:d^O /m:600 /g:on /o: /k:v0 /x: /c:dos"<+!><**>SHELL FALSE,rc,p,c<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>SHOWOFF <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Turn off showing information to the display.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>SHOWOFF<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remark
<:#1450,9360>This statement allows your PPL application to turn off writing information to the local and remote displays. Used in conjunction with the
<+!>SHOWSTAT()<-!> function and the <+!>OPENCAP<-!>, <+!>CLOSECAP<-!>, and
<+!>SHOWON<-!> statements it allows you to temporarily turn off the display while capturing output to the screen. This can be useful anytime you want to automate a feature for the user and allow them to download the resulting capture file instead of spendi
ng lots of time online.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2222,9360>BOOLEAN ss<**>LET ss = SHOWSTAT()<+!><**>SHOWOFF<-!><**>OPENCAP "CAP"+STRING(PCBNODE()),ocFlag<**>IF (ocFlag) THEN<**> DIR "U;NS"<**> CLOSECAP<**> KBDSTUFF "FLAG CAP"+STRING(PCBNODE())+CHR(13)<**>ENDIF<**>IF (ss) THEN<**> SHOWON<**>ELSE<**>
<:#240,9360>Turn on showing information to the display.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>SHOWON<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remark
<:#1450,9360>This statement allows your PPL application to turn on writing information to the local and remote displays. Used in conjunction with the
<+!>SHOWSTAT()<-!> function and the <+!>OPENCAP<-!>, <+!>CLOSECAP<-!>, and
<+!>SHOWOFF<-!> statements it allows you to temporarily turn off the display while capturing output to the screen. This can be useful anytime you want to automate a feature for the user and allow them to download the resulting capture file instead of spend
ing lots of time online.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2222,9360>BOOLEAN ss<**>LET ss = SHOWSTAT()<**>SHOWOFF<**>OPENCAP "CAP"+STRING(PCBNODE()),ocFlag<**>IF (ocFlag) THEN<**> DIR "U;NS"<**> CLOSECAP<**> KBDSTUFF "FLAG CAP"+STRING(PCBNODE())+CHR(13)<**>ENDIF<**>IF (ss) THEN<**>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type and Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if data is being shown on the display,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#1450,9360>This function allows your PPL application to determine the status of writing information to the local and remote displays. Used in conjunction with the
<+!>OPENCAP<-!>, <+!>CLOSECAP<-!>, <+!>SHOWON<-!>, and <+!>SHOWOFF<-!> statements it allows you to temporarily turn off the display while capturing output to the screen. This can be useful anytime you want to automate a feature for the user and allow them
to download the resulting capture file instead of spending lots of time online.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2222,9360>BOOLEAN ss<**>LET ss = <+!>SHOWSTAT()<-!><**>SHOWOFF<**>OPENCAP "CAP"+STRING(PCBNODE()),ocFlag<**>IF (ocFlag) THEN<**> DIR "U;NS"<**> CLOSECAP<**> KBDSTUFF "FLAG CAP"+STRING(PCBNODE())+CHR(13)<**>ENDIF<**>IF (ss) THEN<**> SHOWON<**>ELSE<**> SHOWOFF<**>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the path of the PCBoard login security files.
@Small_Header@<:#259,9360>Remarks
<:#480,9360>This function will return the path where login security files are located as defined in PCBSetup. It can be used to create and change them on the fly.
<:#240,9360>Turn on the speaker on the local computer at a specific frequency.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>SOUND freq<:f>
@Indent_List@<:#480,9360> <:f,QCourier,>freq<:f> An integer expression with the frequency (in hertz) at which to turn on the speaker or 0 to turn off the speaker.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>This statement can be used to generate just about any tone desired on the speaker on the local PC. It has no effect on the remote computer and will only work with the built in speaker (in other words, it has no way of communicating with advanced sound card
s). You specify the frequency of the tone you wish to generate in hertz and pass it to the statement, or pass 0 to turn off the speaker.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2054,9360>PAGEON<**>FOR i = 1 TO 10<**> MPRINT CHR(7)<+!><**> SOUND 440<-!><**> DELAY 9<+!><**> SOUND 0<-!><**> DELAY 9<**> IF (KINKEY() = " ") THEN<**> CHAT<**> GOTO exit<**> ENDIF<**>NEXT<**>:exit
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>SPACE() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Create a string with a specified of spaces.
@Indent_List@<:#240,9360> <:f,QCourier,>len<:f> An integer expression with the number of spaces for the new string.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns a string of len spaces.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function is useful when formatting screen displays without ANSI and when writing formatted information out to a file. It will create a string of the length specified with nothing but spaces. The returned string may have anywhere from 0 to 256 spaces.
@Indent_List@<:#240,9360> <:f,QCourier,>exp<:f> An expression of any type to evaluate and write to the caller's screen.
@Small_Header@<:#259,9360>Remarks
<:#1455,9360>These statements will evalutate zero, one or more expressions of any type and write the results to the BBS for the SysOp's display. The
<+!>SPRINTLN<-!> statement will append a newline to the end of the expressions;
<+!>SPRINT<-!> will not. Note that at least one expression must be specified for
<+!>SPRINT<-!>, unlike the <+!>SPRINTLN<-!> statement which need not have any arguments passed to it. These statements only send information to the local display and do not interpret @ codes; however, complete ANSI sequences will be interpreted.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#948,9360><+!>SPRINT "The name of the currently running PPE file is "<**>SPRINTLN PPENAME(),"."<**>SPRINT "The path where it is located is "<**>SPRINTLN PPEPATH(),"."<**>SPRINT "The date is ",DATE()," and the time is ",TIME(),"."<**>SPRINTLN<-!>
<:#245,9360>Set the allow stacked commands flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>16 = 10000b = 20o = 10h
@Small_Header@<:#259,9360>Remarks
<+C><:#1205,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to allow space and semi-colon characters to be input independent of the valid character string specified. This facilitates entering stacked commands (commands separated by space or semi
-colon delimiters) by only requiring a single value be set in the input statement instead of having to add " ;" to every valid character mask.
<:#240,9360>Start PCBoard's display routines in a specified mode.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>STARTDISP mode<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>mode<:f> An integer expression with the mode for display.
@Small_Header@<:#259,9360>Remarks
<:#1695,9360>PCBoard has two modes for displaying information: non stop and line count. Non stop mode (initiated by passing
<+!>FNS<-!>, for Force Non Stop, as the mode parameter) displays information without regard to how fast the display is or whether or not the user can read it all. Line count mode (initiated by passing
<+!>FCL<-!>, for Force Count Lines, as the mode parameter) displays information while counting lines and pausing after every screenful to wait for user input. Finally,
<+!>NC<-!></`>may be specified to reinitialize the internal display counters without changing the current mode.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1896,9360><+!>STARTDISP FCL<-!><**>FOR i = 1 TO 100<**> PRINTLN "Line ",i<**>NEXT<**><+!>STARTDISP FNS<-!><**>FOR i = 1 TO 100<**> PRINTLN "Line ",i<**>NEXT<**><+!>STARTDISP NC<-!><**>FOR i = 1 TO 100<**> PRINTLN "Line ",i<**>NEXT
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#970,9360>This statement may be used to abnormally terminate PPE execution at any point. The only real difference between this statement and
<+!>END<-!> is whether or not information written to channel 0 is saved when the .
<+!>END<-!> will save the output to the script answer file; <+!>STOP<-!> will not.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2380,9360>STRING Question, Answer<**>LET Question = "What is your street address ..."<**>GOSUB ask<**>INPUTYN "Save address",Answer,@X0E<**>IF (Answer = NOCHAR())
<+!>STOP<-!><**>END<**><**>:ask ' Sub to ask a question, get an answer, and log them to a file<**>LET Answer = ""<**>PRINTLN "@X0E",Question<**>INPUT "",Answer<**>NEWLINES 2<**>FPUTLN 0,"Q: ",STRIPATX(Question)<**>FPUTLN 0,"A: ",Answer<**>RETURN
@Indent_List@<:#720,9360> <:f,QCourier,>var<:f> The name of a variable to declare. Must start with a letter <[>A-Z] which may be followed by letters, digits <[>0-9] or the underscore <[>_]. May be of any length but only the first 32 characters are used.
@Indent_List@<:#480,9360> <:f,QCourier,>arr<:f> The name of an array variable to declare. The same naming conventions as var are used.
@Indent_List@<:#480,9360> <:f,QCourier,>s<:f> The size (0-based) of an array variable dimension. Any constant integer expression is allowed.
@Small_Header@<:#259,9360>Remarks
<:#2185,9360><+!>STRING<-!> variables are stored as pointers arrays of characters from 0 to 257 bytes in size. If the array has 0 or 1 characters in it, it is a 0 length string. Arrays with 2 to 257 characters have a length of the array size minus one. Valid string c
haracters are ASCII 1 through ASCII 255. ASCII 0 is reserved for terminating the string and may not appear in the middle of the string. A
<+!>STRING<-!> assignment to an <+!>INTEGER<-!> will convert the string to the four byte binary integer value (similar to BASIC's VAL function and C's atol function). An
<+!>INTEGER<-!> to <+!>STRING<-!> assignment will result in a string with the representation of the number (similar to BASIC's STR$ function and C's ltoa function). If a
<+!>STRING<-!> is assigned to or from any other type, an appropriate conversion is performed automatically by PPL.
@Indent_List@<:#240,9360> <:f,QCourier,>exp<:f> Any expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns exp formatted as a string.
@Small_Header@<:#259,9360>Remarks
<:#2400,9360>This function is immensely useful anytime you need to convert any expression to string format. For example, to append an integer value to the end of a string without this function, you would need to assign the integer to a string and then append the tempor
ary string to actual string. This is because PPL's normal course of action when performing arithmetic with incompatible types is to convert everything to integer first. With this function, you can accomplish the same function in one line of code with one
expression because you are forcing addition of compatible types (strings). Note that PPL does automatically convert incompatible types whenever possible, making this function unnecessary in many cases. This function should only be necessary when trying to
append the text representation of a non-string type to a string via the + operator.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1610,9360>INTEGER i<**>STRING s(5)<**>FOR i = 1 to 5<**> LET s(i) = "This is string "+<+!>STRING(i)<-!><**>NEXT<**><**>STRING s<**>LET s =
<+!>STRING(ABORT())<-!>+" "+<+!>STRING(DATE())<-!>+" "+<+!>STRING(10)<-!>+" "<**>LET s = s+<+!>STRING($10.00)<-!>+" "+<+!>STRING(TIME())<-!><**>PRINTLN s ' will print "0 10-31-67 10 $10.00 03:27:00" (or similar)
@Small_Header@<:#259,9360><-"><-"><-"><-">See Also
<:#240,9360>
<:p<* >>
@Subhead@<:#360,9360>STRIP() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Remove all occurrences of a character from a string.
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression.
@Indent_List@<:#240,9360> <:f,QCourier,>ch<:f> String with character to remove from str.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns sexp without occurrences of ch that may have been present previously.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function is used to strip a selected character from a string. This can be useful when you need to remove known formatting characters from a string, such as slashes and hyphens from a date string.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>STRING s<**>WHILE (LEN(s) << 6) DO<**> INPUTSTR "Enter date (MM-DD-YY)",s,@X0E,8,"0123456789-",DEFS<**> LET s =
@Indent_List@<:#240,9360> <:f,QCourier,>sexp<:f> Any string expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns sexp without any @X codes that may have been present previously.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function is used to strip PCBoard @X color codes from a string or string expression. This is useful when you want to log information to a file without the @X codes used in the screen display.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1896,9360>STRING Question, Answer<**>LET Question = "What is your street address ..."<**>GOSUB ask<**>END<**>:ask ' Sub to ask a question, get an answer, and log them to a file<**>LET Answer = ""<**>PRINTLN "@X0E",Question<**>INPUT "",Answer<**>NEWLINES 2<**>FPUTLN 0
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the SysOp security level as defined in PCBSetup.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function is useful for those occasions when you need to limit functionality in your PPL applications to users having a security level greater than or equal to the defined SysOp security level in PCBSetup.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1274,9360>INTEGER min<**>IF (CURSEC() <;>= <+!>SYSOPSEC()<-!>) THEN<**> LET min = 60<**>ELSE<**> LET min = 5<**>ENDIF<**>ADJTIME min<**>PRINTLN "Your time available has been increased by ",min," minutes"
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>S_DB <+">Constant<-">
@Small_Header@<:#259,9360>Function
<:#245,9360>Set the share deny both (read and write) flag in a <+!>FCREATE<-!>/<+!>FOPEN<-!>/<+!>FAPPEND<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>3 = 11b = 3o = 3h
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>DOS 3.1 or later (which is what is required by PCBoard) allows processes to decide what mode of file sharing should be allowed. This constant allows you to specify that other processes may not open the same file for either read or write access from the tim
e you open the file to the time you close the file. This is useful when you need exclusive access to a file for any reason and need to restrict other processes access to the same file.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>FOPEN 1,"FILE.DAT",O_RD,<+!>S_DB<-!> ' Deny other processes all access<**>FOR i = 1 TO 10<**> FGET 1,s<**> PRINTLN s<**>NEXT<**>FCLOSE 1 ' Close the file and allow others to open it in any mode
<:#245,9360>Set the share deny none flag in a <+!>FCREATE<-!>/<+!>FOPEN<-!>/<+!>FAPPEND<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>0 = 0b = 0o = 0h
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>DOS 3.1 or later (which is what is required by PCBoard) allows processes to decide what mode of file sharing should be allowed. This constant allows you to specify that other processes may open the same file for read or write access from the time you open
the file to the time you close the file. This is useful when you don't need exclusive access to a file for any reason and need not restrict other processes.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>FOPEN 1,"FILE.DAT",O_RD,<+!>S_DN<-!> ' Do not deny other processes any access<**>FOR i = 1 TO 10<**> FGET 1,s<**> PRINTLN s<**>NEXT<**>FCLOSE 1 ' Close the file and allow others to open it in any mode
<:#245,9360>Set the share deny read flag in a <+!>FCREATE<-!>/<+!>FOPEN<-!>/<+!>FAPPEND<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>1 = 1b = 1o = 1h
@Small_Header@<:#259,9360>Remarks
<:#960,9360>DOS 3.1 or later (which is what is required by PCBoard) allows processes to decide what mode of file sharing should be allowed. This constant allows you to specify that other processes may open the same file, but that they may not open it for read access,
from the time you open the file to the time you close the file.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>FOPEN 1,"FILE.DAT",O_RD,<+!>S_DR<-!> ' Deny other processes read access<**>FOR i = 1 TO 10<**> FGET 1,s<**> PRINTLN s<**>NEXT<**>FCLOSE 1 ' Close the file and allow others to open it in any mode
<:#245,9360>Set the share deny write flag in a <+!>FCREATE<-!>/<+!>FOPEN<-!>/<+!>FAPPEND<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>2 = 10b = 2o = 2h
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>DOS 3.1 or later (which is what is required by PCBoard) allows processes to decide what mode of file sharing should be allowed. This constant allows you to specify that other processes may open the same file, but that they may not open it for write access,
from the time you open the file to the time you close the file. This is useful when you want to ensure that data will not change while you are reading it.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>FOPEN 1,"FILE.DAT",O_RD,<+!>S_DW<-!> ' Deny other processes write access<**>FOR i = 1 TO 10<**> FGET 1,s<**> PRINTLN s<**>NEXT<**>FCLOSE 1 ' Close the file and allow others to open it in any mode
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the path of the node temporary work files area.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>This function will return the path where temporary work files should be created as defined in PCBSetup. This path is a good place for small temporary files that need not be kept permanently since it often points to a RAM drive or other fast local storage.
@Indent_List@<:#720,9360> <:f,QCourier,>var<:f> The name of a variable to declare. Must start with a letter <[>A-Z] which may be followed by letters, digits <[>0-9] or the underscore <[>_]. May be of any length but only the first 32 characters are used.
@Indent_List@<:#480,9360> <:f,QCourier,>arr<:f> The name of an array variable to declare. The same naming conventions as var are used.
@Indent_List@<:#480,9360> <:f,QCourier,>s<:f> The size (0-based) of an array variable dimension. Any constant integer expression is allowed.
@Small_Header@<:#259,9360>Remarks
<:#2430,9360><+!>TIME<-!> variables are stored as seconds elapsed since midnight. Valid times are 0 (00:00:00) through 86399 (23:59:59). It is stored internally as a four byte unsigned long integer. If a
<+!>TIME<-!> is assigned to or from an <+!>INTEGER<-!> type then the seconds since midnight (0-86399) is assigned. If a
<+!>TIME<-!> is assigned to a <+!>STRING<-!> type then it is automatically converted to the following format: "HH:MM:SS", where HH is the two digit hour (00-23), MM is the two digit minute (00-59), and SS is the two digit second (00-59). If a foreign lang
uage is in use that uses a different time format (for example, "HH.MM.SS") then that will be taken into account. If a
<+!>STRING<-!></`>is assigned to a <+!>TIME<-!> then PPL will do it's best to convert the string back to the appropriate time. All other types, when assigned to or from a
<+!>TIME<-!>, will be converted to an <+!>INTEGER<-!> first before being assigned to or from the
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>TIME<-!> Returns the current time.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>The time returned is represented internally as the number of seconds elapsed since midnight. It may be used as is (for display, storage or as an argument to another function or statement) or assigned to an integer for arithmetic purposes. 00:00:00 (midnig
ht) has a value of 0, 00:00:01 a value of 1, 00:01:00 a value of 60, 01:00:00 a value of 3600, etc, until 23:59:59 which has a value of 86399.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "The time is ",<+!>TIME()<-!>
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-">
<:p<* >>
@Subhead@<:#360,9360>TIMEAP() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Converts a time value to a 12-hour AM/PM formatted string.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>TIMEAP(texp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>texp<:f> Any time expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns a string formatted with the time specified by texp in a 12-hour AM/PM format.
@Small_Header@<:#259,9360>Remarks
<:#965,9360><+!>TIME<-!> values are, by default, formatted for military time ("HH:MM:SS") when displayed or assigned to a string variable. You may wish to format them in a 12-hour AM/PM format in some circumstances, however. This function perform the conversion and f
ormat the time in "HH:MM:SS XM" format (HH = hour, MM = minute, SS = second, X = A or P).
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "The current time is ",<+!>TIMEAP(TIME())<-!>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the number of tokens available.
@Small_Header@<:#259,9360>Remarks
<:#1935,9360>Parameter passing between PCBoard and PPL applications (and between PPL applications) and command line parsing is accomplished via tokens. This function will return the number of tokens available via the
<+!>GETTOKEN<-!> statement and the <+!>GETTOKEN()<-!> function. The value returned by this will be decremented after each token is retrieved until it reaches 0 (no more tokens available). The
<+!>TOKENIZE<-!> function will overwrite any pending tokens with new tokens and reinitialize this function to the new number. Finally, the
<+!>TOKENSTR()<-!> function will clear this function to 0 and return all tokens in a string with semi-colons separating individual tokens.<-">
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#336,9360>PRINTLN "There are ",<+!>TOKCOUNT()<-!>," tokens"<**>WHILE (<+!>TOKCOUNT()<-!> <;> 0) PRINTLN GETTOKEN()
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-">
<:p<* >>
@Subhead@<:#360,9360>TOKENIZE <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Split up a string into tokens separated by semi-colons or spaces.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>TOKENIZE sexp<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>sexp<:f> Any string expression.
@Small_Header@<:#259,9360>Remarks
<:#1700,9360>One of the strongest features of PCBoard is it's ability to take a series of stacked parameters from a command line and use them all at once instead of requiring the user to navigate a series of menus and select one option at each step of the way. The
<+!>TOKENIZE<-!> statement is the PPL equivalent of what PCBoard uses to break a command line into individual commands (tokens). The number of tokens available may be accessed via the
<+!>TOKCOUNT()<-!> function, and each token may be accessed, one at a time, by the
<+!>GETTOKEN<-!> statement and/or the <+!>GETTOKEN()<-!> function.
<:#240,9360>Rebuild and return a previously tokenized string.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>TOKENSTR()<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the rebuilt string that was previously tokenized.
@Small_Header@<:#259,9360>Remarks
<:#2170,9360>One of the strongest features of PCBoard is it's ability to take a series of stacked parameters from a command line and use them all at once instead of requiring the user to navigate a series of menus and select one option at each step of the way. The
<+!>TOKENIZE<-!> statement is the PPL equivalent of what PCBoard uses to break a command line into individual commands (tokens). This function will take all pending tokens and build a string with appropriate token separators. For example, the string "R A
S" would be broken into three separate tokens; "R", "A" and "S".
<+!>TOKENSTR()<-!> would take those tokens and return the following string: "R;A;S". Note that, regardless of the separator used in the original string, the semi-colon character will be used in the rebuilt string.
<:#240,9360>Trim a specified character from both ends of a string.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>TRIM(str,ch)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression.
@Indent_List@<:#240,9360> <:f,QCourier,>ch<:f> A string with the character to strip from both ends of str.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the trimmed str.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>A common need in programming is to strip leading and/or trailing spaces (or other characters). This function will strip a specified character from both ends of a string and return the trimmed string.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#820,9360>STRING s<**>LET s = " TEST "<**>PRINTLN <+!>TRIM(s," ")<-!> ' Will print "TEST"<**>PRINTLN
<+!>TRIM(".....DA"+"TA.....",".")<-!> ' Will print "DATA"<**>PRINTLN
<+!>TRIM(".....DA"+"TA....."," ")<-!> ' Will print ".....DATA....."
<:#240,9360>To provide a named constant for the boolean true value in boolean expressions.
@Small_Header@<:#259,9360>Value
<:#240,9360>1 = 1b = 1o = 1h
@Small_Header@<:#259,9360>Remarks
<:#970,9360><+!>BOOLEAN<-!> logic is based on two values: <+!>TRUE<-!> (1) and
<+!>FALSE<-!> (0). The literal numeric constants 0 and 1 may be used in expressions, or you may use the predefined named constants
<+!>TRUE<-!> and <+!>FALSE<-!>. They make for more readable, maintainable code and have no more overhead than any other constant value at run time.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1126,9360>BOOLEAN flag<**>LET flag = <+!>TRUE<-!><**>WHILE (!flag) DO<**> INPUTSTR "Text",s,@X0E,60,"ABCDEFGHIJKLMNOPQRSTUVWXYZ ",<+!>UPCASE<-!><**> PRINTLN s<**> IF (s = "QUIT") LET flag = FALSE<**>ENDWHILE
@Indent_List@<:#240,9360> No arguments are required
<:#240,9360>UN_ should be followed by one of the following: CITY, NAME, OPER, or STAT.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns a string with the desired piece of information.
@Small_Header@<:#259,9360>Remarks
<:#1215,9360>There are actually four different functions that return information from the USERNET.XXX file.
<+!>UN_CITY()<-!> will return the city field, <+!>UN_NAME()<-!> will return the user name field,
<+!>UN_OPER()<-!> will return the operation text field, and <+!>UN_STAT()<-!> will return the status field. The information returned by these functions is only meaningful after executing the
<+!>RDUNET<-!> statement for a specific node.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#652,9360>RDUNET PCBNODE()<**>WRUNET PCBNODE(),<+!>UN_STAT()<-!>,<+!>UN_NAME()<-!>,<+!>UN_CITY()<-!>,"Running "+PPENAME(),""<**>RDUNET 1<**>WRUNET 1,<+!>UN_STAT()<-!>,<+!>UN_NAME()<-!>,<+!>UN_CITY()<-!>,<+!>UN_OPER()<-!>,"Hello there node 1"
<:#245,9360>Set the force uppercase flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>8 = 1000b = 10o = 8h
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to force all input characters to uppercase. This is useful in getting case insensitive replies from the user. If this flag is used, you need not pass lowercase valid characters as they
will be automatically converted at runtime. If this flag is not used and you need to input alphabetic characters, you should pass both lowercase and uppercase characters in the valid character string.
<:#240,9360>Converts lowercase characters in a string to uppercase.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>UPPER(sexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>sexp<:f> Any string expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns sexp with all lowercase characters converted to uppercase.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>Although "STRING" is technically different from "string" (ie, the computer doesn't recognize them as being the same because one is uppercase and the other is lowercase), it is often necessary to save, display or compare information in a case insensitive for
mat. This function will return a string with all lowercase characters converted to uppercase. So, using the above example,
<:s><:#240,9360>Allow reading and writing of the current users address information.
@Small_Header@<:s><:#259,9360>Type & Value
<:s><:#240,9360><+!>STRING<-!>
@Indent_List@<:#240,9360> Subscript 0 Address Line 1 (50 characters max).
@Indent_List@<:#240,9360> Subscript 1 Address Line 2 (50 characters max).
@Indent_List@<:#240,9360> Subscript 2 City (25 characters max).
@Indent_List@<:#240,9360> Subscript 3 State (10 characters max).
@Indent_List@<:#240,9360> Subscript 4 ZIP Code (10 characters max).
@Indent_List@<:#240,9360> Subscript 5 Country (15 characters max).
@Small_Header@<:s><:#259,9360>Remarks
<:#1460,9360>This array is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that the array is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Additionally, the array will only have meaningful information if the address PSA is installed. The existence of the address PSA may be checked with the
<:s><:#240,9360>Allow reading and writing of the current users alias.
@Small_Header@<:s><:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> The current users alias (25 characters max).
@Small_Header@<:s><:#259,9360>Remarks
<:#1460,9360>This <+!>STRING<-!> is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Additionally, it will only have meaningful information if the alias PSA is installed. The existence of the alias PSA may be checked with the
<+!>PSA()<-!> function.
@Small_Header@<:s><:#259,9360>Examples
@Example_Text@<:#958,9360>IF (PSA(1)) THEN<**> GETUSER<**> PRINTLN "Your alias is ",<+!>U_ALIAS<-!><**>ELSE<**> PRINTLN "Your name is ",U_NAME()<**>ENDIF
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current users total bytes downloaded.
@Small_Header@<:#259,9360>Remarks
<:#1210,9360>This function will return information that can be useful in modifying PCBoard's built in ratio management system and the view user information command. Of course, it is not limited to that; anywhere you need to know how many bytes the current user has down
loaded, this function will provide that information. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You have ULed ",U_BUL()," bytes and DLed ",<+!>U_BDL()<-!>," bytes."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_BDLDAY() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Access the number of bytes downloaded by the current user today.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current users bytes downloaded today.
@Small_Header@<:#259,9360>Remarks
<:#1210,9360>This function will return information that can be useful in modifying PCBoard's built in ratio management system and the view user information command. Of course, it is not limited to that; anywhere you need to know how many bytes the current user has down
loaded today, this function will provide that information. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You have downloaded ",<+!>U_BDLDAY()<-!>," bytes today."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_BDPHONE <+">VARIABLE<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Allow reading and writing of the current users business/data phone number.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> The current users business/data phone number (13 characters max).
@Small_Header@<:#259,9360>Remarks
<:#975,9360>This <+!>STRING<-!> is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current users total bytes uploaded.
@Small_Header@<:#259,9360>Remarks
<:#1210,9360>This function will return information that can be useful in modifying PCBoard's built in ratio management system and the view user information command. Of course, it is not limited to that; anywhere you need to know how many bytes the current user has uplo
aded, this function will provide that information. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You have ULed ",<+!>U_BUL()<-!>," bytes and DLed ",U_BDL()," bytes."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_CITY <+">VARIABLE<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Allow reading and writing of the current users city information.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> The current users city information (24 characters max).
@Small_Header@<:#259,9360>Remarks
<:#1455,9360>This <+!>STRING<-!> is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Note that this information is separate from the address PSA and does not require that the address PSA be installed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>GETUSER<**>LET <+!>U_CITY<-!> = "Timbuktu"<**>PRINTLN "You are now from Timbuktu! :)"<**>PUTUSER
<:#240,9360>Allow reading and writing of the current users comment field.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> The current users comment field (30 characters max).
@Small_Header@<:#259,9360>Remarks
<:#1455,9360>This <+!>STRING<-!> is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Note that this information is separate from the notes PSA (though similar) and does not require that the notes PSA be installed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#484,9360>GETUSER<**>PRINTLN " User Comment: ",<+!>U_CMNT1<-!><**>PRINTLN "SysOp Comment: ",U_CMNT2
<:#240,9360>Allow reading and writing of the current users SysOp comment field.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> The current users SysOp comment field (30 characters max).
@Small_Header@<:#259,9360>Remarks
<:#1455,9360>This <+!>STRING<-!> is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Note that this information is separate from the notes PSA (though similar) and does not require that the notes PSA be installed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#484,9360>GETUSER<**>PRINTLN " User Comment: ",U_CMNT1<**>PRINTLN "SysOp Comment: ",<+!>U_CMNT2<-!>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current users total files downloaded.
@Small_Header@<:#259,9360>Remarks
<:#1210,9360>This function will return information that can be useful in modifying PCBoard's built in ratio management system and the view user information command. Of course, it is not limited to that; anywhere you need to know how many files the current user has down
loaded, this function will provide that information. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You have ULed ",U_FUL()," bytes and DLed ",<+!>U_FDL()<-!>," files."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_FSE <+">VARIABLE<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Allow reading and writing of the current users full screen editor default flag.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> The current users full screen editor default flag status (<+!>TRUE<-!> or
<+!>FALSE<-!>).
@Small_Header@<:#259,9360>Remarks
<:#975,9360>This <+!>BOOLEAN<-!> is set with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is undefined until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>GETUSER<**>PRINTLN "Turning on full screen editor as default..."<**>LET
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current users total files uploaded.
@Small_Header@<:#259,9360>Remarks
<:#1210,9360>This function will return information that can be useful in modifying PCBoard's built in ratio management system and the view user information command. Of course, it is not limited to that; anywhere you need to know how many files the current user has uplo
aded, this function will provide that information. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You have ULed ",<+!>U_FUL()<-!>," bytes and DLed ",U_FDL()," files."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_HVPHONE <+">VARIABLE<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Allow reading and writing of the current users home/voice phone number.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> The current users home/voice phone number (13 characters max).
@Small_Header@<:#259,9360>Remarks
<:#975,9360>This <+!>STRING<-!> is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
@Indent_List@<:#240,9360> <:f,QCourier,>rec<:f> An integer expression with the record number of the user to check.
@Indent_List@<:#240,9360> <:f,QCourier,>conf<:f> An integer expression with the conference number to check.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if the user is registered in the specified conference,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>It is sometimes necessary to know if a user is registered in a conference (for example, when entering a message to a particular user). This function will return
<+!>TRUE<-!> if the user is registered in the conference specified. Before calling this function you need to find the users record number from the USERS file with the
<+!>U_RECNUM()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1590,9360>INTEGER i,rec<**>STRING un,ynStr(1)<**>LET ynStr(0) = "NO"<**>LET ynStr(1) = "YES"<**>INPUT "User name",un<**>NEWLINE<**>LET rec = U_RECNUM(un)<**>FOR i = 1 TO 10<**> PRINTLN un," in conf ",i,": ",ynStr(<+!>U_INCONF(i,rec)<-!>)<**>NEXT
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>DATE<-!> Returns the current users last log on date.
@Small_Header@<:#259,9360>Remarks
<:#730,9360>PCBoard tracks the last log on date for each user. This function will return that date for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You last logged on ",<+!>U_LDATE()<-!>,"."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_LDIR() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Access the latest file date found in a file scan by a user.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>DATE<-!> Returns the latest file date found by the current user.
@Small_Header@<:#259,9360>Remarks
<:#730,9360>PCBoard tracks the latest file found by each user. This function will return that date for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "Latest file found was dated ",<+!>U_LDIR()<-!>,"."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_LOGONS() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Access the total number of system logons by the current user.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current users total system logons.
@Small_Header@<:#259,9360>Remarks
<:#730,9360>PCBoard tracks the total number of logons for each user. This function will return that number for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You have logged on to @BOARDNAME@ ",<+!>U_LOGONS()<-!>," times."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_LONGHDR <+">VARIABLE<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Allow reading and writing of the current users long message header flag.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> The current users long message header flag status (<+!>TRUE<-!> or
<+!>FALSE<-!>).
@Small_Header@<:#259,9360>Remarks
<:#975,9360>This <+!>BOOLEAN<-!> is set with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is undefined until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>GETUSER<**>PRINTLN "Turning on long message headers..."<**>LET <+!>U_LONGHDR<-!> = TRUE<**>PUTUSER
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>TIME<-!> Returns the time of day of the current users last log on.
@Small_Header@<:#259,9360>Remarks
<:#730,9360>PCBoard tracks the last time of day of the last log on for each user. This function will return that time for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You last logged on at ",<+!>U_LTIME()<-!>,"."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_MSGRD() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Access the total number of messages read by the current user.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current users total messages read.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>PCBoard tracks the total number of messages read by each user. This function will return that number for the user currently online. One quick idea for use: a message/file ratio enforcement door. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>IF ((<+!>U_MSGRD()<-!>+U_MSGWR())/U_FDL() <;> 10) THEN<**> PRINTLN "You need to do more messaging!!!"<**> END<**>ENDIF
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_MSGWR() <+">Function<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Access the total number of messages written by the current user.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the current users total messages written.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>PCBoard tracks the total number of messages written by each user. This function will return that number for the user currently online. One quick idea for use: a message/file ratio enforcement door. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>IF ((U_MSGRD()+<+!>U_MSGWR()<-!>)/U_FDL() <;> 10) THEN<**> PRINTLN "You need to do more messaging!!!"<**> END<**>ENDIF
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns a string with the current users name.
@Small_Header@<:#259,9360>Remarks
<:#1205,9360>Perhaps the most important piece of information about a caller is his name. The user name differentiates a user from every other user on the BBS and can be used to track PPE user information that must be kept separate from all other users information. Unl
ike the predefined <+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>IF (<+!>U_NAME()<-!> = "JOHN DOE) THEN<**> PRINTLN "I know who you are! Welcome!"<**> GETUSER<**> LET U_SEC = 110<**> PUTUSER<**> PRINTLN "Automatically upgraded!"<**>ENDIF
<:#240,9360>Allow reading and writing of current user notes.
@Small_Header@<:#259,9360>Type & Value
<:#240,9360><+!>STRING<-!>
@Indent_List@<:#240,9360> Subscript 0-4 SysOp defineable user notes (60 characters max).
@Small_Header@<:#259,9360>Remarks
<:#1460,9360>This array is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that the array is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Additionally, the array will only have meaningful information if the notes PSA is installed. The existence of the notes PSA may be checked with the
<+!>PSA()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1116,9360>INTEGER i<**>IF (PSA(6)) THEN<**> GETUSER<**> FOR i = 0 TO 4<**> PRINTLN "Note ",i+1,": ",<+!>U_NOTES(i)<-!><**> NEXT<**>ENDIF
<:#240,9360>Allow reading and writing of the current users password expiration date.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>DATE<-!> The current users password expiration date.
@Small_Header@<:#259,9360>Remarks
<:#1460,9360>This <+!>DATE<-!> is set with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is undefined until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Additionally, it will only have meaningful information if the password PSA is installed. The existence of the password PSA may be checked with the
<+!>PSA()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1126,9360>IF (PSA(4)) THEN<**> GETUSER<**> PRINTLN <+!>U_PWDEXP<-!>-DATE()," until current password expiration"<**> LET
<+!>U_PWDEXP<-!> = DATE()+30<**> PRINTLN "You now have 30 days until you *MUST* change you password."<**> PUTUSER<**>ENDIF
@Indent_List@<:#240,9360> <:f,QCourier,>num<:f> The number of the password from the history to return (1 through 3).
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>STRING<-!> Returns the specified password from the history (1 for the most recent, 3 for the least recent).
@Small_Header@<:#259,9360>Remarks
<:#1450,9360>PCBoard has the ability to track the last three passwords used by each user. This function will return one of those passwords from the history for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information. However, it does require that the password PSA has been installed to return meaningful information. The existence of the password PSA may be checked via the
<+!>PSA()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#958,9360>INTEGER i<**>IF (PSA(4)) THEN<**> FOR i = 1 TO 3<**> PRINTLN "Password history ",i,": ",<+!>U_PWDHIST(i)<-!><**> NEXT<**>ENDIF
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>DATE<-!> Returns the last date the user changed his password.
@Small_Header@<:#259,9360>Remarks
<:#1215,9360>PCBoard has the ability to track the last date of a password change for each user. This function will return that date for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information. However, it does require that the password PSA has been installed to return meaningful information. The existence of the password PSA may be checked via the
<+!>PSA()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>IF (PSA(4)) PRINTLN "You last changed your password on ",<+!>U_PWDLC()<-!>,"."
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the number of times the user has changed his password.
@Small_Header@<:#259,9360>Remarks
<:#1455,9360>PCBoard has the ability to track the total number of times each user changes his password. This function will return that count for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information. However, it does require that the password PSA has been installed to return meaningful information. The existence of the password PSA may be checked via the
<+!>PSA()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#484,9360>IF (PSA(4)) THEN<**> PRINTLN "You have changed your password ",<+!>U_PWDTC()<-!>," times."<**>ENDIF
@Indent_List@<:#240,9360> <:f,QCourier,>user<:f> A string expression with the user name to search for.
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>INTEGER<-!> Returns the record number of the user in the USERS file if found or -1 if not found.
@Small_Header@<:#259,9360>Remarks
<:#965,9360>This function serves two purposes. The first is to determine whether or not a given user name is registered on the system. If the value -1 is returned the user isn't in the user files. The second use is to get the users record number for the
<+!>U_INCONF()<-!> function to determine whether or not a user is registered in a given conference.
@Indent_List@<:#240,9360> <:f,QCourier,>stat<:f> The statistic to retrieve (1 through 15).
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>DATE<-!> Returns the first date the user called the system if stat is 1.
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns one of the following for all other values of stat:
@Indent_List@<:#240,9360> 2 The number of times the user has paged the SysOp;
@Indent_List@<:#240,9360> 3 The number of group chats the user has participated in;
@Indent_List@<:#240,9360> 4 The number of comments left by the user;
@Indent_List@<:#240,9360> 5 The number of 300 bps connects by the user;
@Indent_List@<:#240,9360> 6 The number of 1200 bps connects by the user;
@Indent_List@<:#240,9360> 7 The number of 2400 bps connects by the user;
@Indent_List@<:#480,9360> 8 The number of connects by the user greater than 2400 bps and less than or equal to 9600 bps (9600 bps <;>= connect speed <;> 2400 bps);
@Indent_List@<:#480,9360> 9 The number of connects by the user greater than 9600 bps and less than or equal to 14,400 bps (14,400 bps <;>= connect speed <;> 9600 bps);
@Indent_List@<:#240,9360> 10 The number of security violations by the user;
@Indent_List@<:#240,9360> 11 The number of "not registered in conference" warnings to the user;
@Indent_List@<:#240,9360> 12 The number of times the user's download limit has been reached;
@Indent_List@<:#240,9360> 13 The number of "file not found" warnings to the user;
@Indent_List@<:#240,9360> 14 The number of password errors to access the user's account;
@Indent_List@<:#240,9360> 15 The number of verify errors to access the user's account.
@Small_Header@<:#259,9360>Remarks
<:#1215,9360>PCBoard has the ability to track a number of statistics about the user. This function will return the desired statistic for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information. However, it does require that the statistics PSA has been installed to return meaningful information. The existence of the statistics PSA may be checked via the
<+!>PSA()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1274,9360>STRING label<**>INTEGER i<**>FOPEN 1,PPEPATH()+"STATTEXT",O_RD,S_DN<**>FOR i = 1 TO 15<**> FGET 1,label<**> PRINTLN label," - ",<+!>U_STAT(i)<-!><**>NEXT<**>FCLOSE 1
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the users time online today in minutes.
@Small_Header@<:#259,9360>Remarks
<:#730,9360>PCBoard tracks the users time online each day. This function will return the elapsed time for the user currently online. Unlike the predefined
<+!>U_...<-!> user variables, this function does not require the use of
<+!>GETUSER<-!> to return valid information.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#168,9360>PRINTLN "You have been online for ",<+!>U_TIMEON()<-!>," total minutes today."
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-"><-">
<:p<* >>
@Subhead@<:#360,9360>U_TRANS <+">VARIABLE<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Allow reading and writing of the current users default transfer protocol letter.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> The current users default transfer protocol letter (1 character max).
@Small_Header@<:#259,9360>Remarks
<:#1220,9360>This <+!>STRING<-!> is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Valid characters that may be used in the
<+!>U_TRANS<-!></`>variable are A through Z and 0 through 9.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#810,9360>GETUSER<**>PRINTLN "Your default file transfer protocol letter is ",<+!>U_TRANS<-!><**>LET
<+!>U_TRANS<-!> = "N" ' Set to no default protocol<**>PRINTLN "Default file transfer protocol letter set to None"<**>PUTUSER
<:#240,9360>Allow reading and writing of the current users verification string.
@Small_Header@<:#259,9360>Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> The current users verification string (25 characters max).
@Small_Header@<:#259,9360>Remarks
<:#1460,9360>This <+!>STRING<-!> is filled with information from the current users record when the
<+!>GETUSER<-!> statement is executed. It may then be changed and written back to the users record with the
<+!>PUTUSER<-!> statement. Note that it is empty until a <+!>GETUSER<-!> statement is processed and that changes are not written until a
<+!>PUTUSER<-!> statement is processed. Additionally, it will only have meaningful information if the verification PSA is installed. The existence of the verification PSA may be checked with the
<+!>PSA()<-!> function.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1432,9360>STRING s<**>IF (PSA(2)) THEN<**> GETUSER<**> PRINTLN "Enter verification information"<**> INPUT "",s<**> IF (s <<<;>
<+!>U_VER<-!>) HANGUP<**>ELSE<**> PRINTLN "No verification information available"<**>ENDIF
<:#240,9360>Tests a string for credit card number format validity.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>VALCC(sexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>sexp<:f> Any string expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#485,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if the string is a valid credit card number format,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#725,9360>This function will take a string and attempt to identify it as a credit card number. If the number is invalid for any reason (insufficient digits or bad checksum, primarily) then this function will return
<+!>FALSE<-!>, otherwise it will return <+!>TRUE<-!>.
<:#240,9360>Tests a string for date format validity.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>VALDATE(sexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>sexp<:f> Any string expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if the string is a valid date format,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#1695,9360>PPL does it best to convert incompatible types, as needed, automatically. Converting a
<+!>STRING<-!> type to a <+!>DATE<-!> type is particularly problematic because of the virtually unlimited numbers of strings possible. This function checks to make sure that the hour is from 0 to 23, the minute is from 0 to 59, and the second (optional) is
from 0 to 59. Also, each field (hours/minutes/seconds) must be separated by a colon. If the string matches these requirements then the string is considered valid and
<+!>TRUE<-!></`>is returned. Any other string will result in a <+!>FALSE<-!> value being returned.
<:#240,9360>Tests a string for time format validity.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>VALTIME(sexp)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>sexp<:f> Any string expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>BOOLEAN<-!> Returns <+!>TRUE<-!> if the string is a valid time format,
<+!>FALSE<-!> otherwise.
@Small_Header@<:#259,9360>Remarks
<:#1695,9360>PPL does it best to convert incompatible types, as needed, automatically. Converting a
<+!>STRING<-!> type to a <+!>TIME<-!> type is particularly problematic because of the virtually unlimited numbers of strings possible. This function checks to make sure that the hour is from 0 to 23, the minute is from 0 to 59, and the second (optional) is
from 0 to 59. Also, each field (hours/minutes/seconds) must be separated by a colon. If the string matches these requirements then the string is considered valid and
<+!>TRUE<-!></`>is returned. Any other string will result in a <+!>FALSE<-!> value being returned.
<:#240,9360>Sets a variable to the complete address of another variable.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>VARADDR src,dest<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>src<:f> The variable to get the address of.
@Indent_List@<:#240,9360> <:f,QCourier,>dest<:f> The variable to store the address in.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>This statement is primarily useful in conjunction with the <+!>DOINTR<-!> statement. It may be necessary to give an interrupt the address of a memory location that can be used to store information. This statement will allow you to get the address of a spe
cified variable to pass to the <+!>DOINTR<-!></`>statement.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2370,9360>' Create subdirectory - DOS function 39h<**>INTEGER addr<**>STRING path<**>LET path = "C:\$TMPDIR$"<+!><**>VARADDR path,addr<-!><**>DOINTR 21h,39h,0,0,addr%10000h,0,0,0,addr/10000h,0<**>IF (REGCF() & (REGAX() = 3)) THEN<**> PRINTLN "Error: Path not found
<:#240,9360>Sets a variable to the offset address of another variable.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>VAROFF src,dest<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>src<:f> The variable to get the offset address of.
@Indent_List@<:#240,9360> <:f,QCourier,>dest<:f> The variable to store the offset address in.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>This statement is primarily useful in conjunction with the <+!>DOINTR<-!> statement. It may be necessary to give an interrupt the address of a memory location that can be used to store information. This statement will allow you to get the offset address o
f a specified variable to pass to the <+!>DOINTR<-!></`>statement.
<:#240,9360>Sets a variable to the segment address of another variable.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>VARSEG src,dest<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>src<:f> The variable to get the segment address of.
@Indent_List@<:#240,9360> <:f,QCourier,>dest<:f> The variable to store the segment address in.
@Small_Header@<:#259,9360>Remarks
<:#970,9360>This statement is primarily useful in conjunction with the <+!>DOINTR<-!> statement. It may be necessary to give an interrupt the address of a memory location that can be used to store information. This statement will allow you to get the segment address
of a specified variable to pass to the <+!>DOINTR<-!></`>statement.
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the version number of PPL running.
@Small_Header@<:#259,9360>Remarks
<:#1690,9360>As time passes, new features will be added to PCBoard and PPL. Of course, in order to utilize the new features, you must be running a version of PCBoard that supports them. This function will return the version of PCBoard (and PPL). For PCBoard version 1
5.0 this value will be 1500. In other words, the major version will be accessable via
<+!>VER()<-!>/100, and the minor version will be available via <+!>VER()<-!>%100. Everything documented herein will be available for all versions greater than or equal to 1500. Future PPL features will be documented with the required version.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#800,9360>IF (<+!>VER()<-!> << 1600) THEN<**> PRINTLN "PCBoard Version 16.0 required for this PPE file"<**> END<**>ENDIF<**>FOO a,b,c,d,e ' Obviously, this is not a 15.0 statement
@Small_Header@<:#259,9360>See Also
<:#240,9360><-"><-"><-">
<:p<* >>
@Subhead@<+@><:#360,9360>WAIT <+">Statement<-">
@Small_Header@<:#259,9360>Function
<:#240,9360>Wait for the user to hit ENTER.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>WAIT<:f>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#960,9360>It is often necessary to pause in the display of information and wait for the user to catch up. This statement allows you to wait for the user to hit ENTER before continuing. It displays prompt number 418 from the PCBTEXT file for the current language to
let the user know what is expected.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#474,9360>PRINTLN "Your account has expired!"<**>PRINTLN "You are about to be logged off"<**><+!>WAIT<-!>
@Indent_List@<:#240,9360> <:f,QCourier,>str<:f> Any string expression.
@Indent_List@<:#240,9360> <:f,QCourier,>flag<:f> A variable to return the status.
@Indent_List@<:#240,9360> <:f,QCourier,>sec<:f> An integer expression with the maximum number of seconds to wait.
@Small_Header@<:#259,9360>Remarks
<:#1700,9360>This statement can be used to wait for specific replies to questions, responses from terminal emulators and modem result codes. If the text that is needed isn't received within the specified time period, or if there is not a remote caller online, flag will
be set to <+!>FALSE<-!>. If the text is found, then flag will be
<+!>TRUE<-!>. If a remote caller is online this statement will wait up to the maximum time for the text and return
<+!>TRUE<-!> or <+!>FALSE<-!> as appropriate. If the caller is local, it will immediately return
<+!>FALSE<-!>. Also, the text to wait for is not case sensitive. "connect" will match "CONNECT".
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1738,9360>BOOLEAN flag<**>KBDCHKOFF<**>CDCHKOFF<**>DTROFF<**>DELAY 18<**>DTRON<**>SENDMODEM "ATDT5551212" ' Please don't really dial this number!<+!><**>WAITFOR "CONNECT",flag,60<-!><**>IF (!flag) SPRINLN "No connect found in 60 seconds"<**>CDCHKON<**>KBDCHKON
@Indent_List@<:#240,9360> <:f,QCourier,>bexp<:f> Any boolean expression.
@Indent_List@<:#240,9360> <:f,QCourier,>statement<:f> Any valid PPL statement.
@Small_Header@<:#259,9360>Remarks
<:#2670,9360>Computers are known for their ability to perform monotonous tasks quickly, efficiently, and accurately. What better way to implement monotony than through a
<+!>WHILE<-!> loop? The <+!>WHILE<-!> statement supports two types of loops: logical and block. A logical
<+!>WHILE<-!> loop is a single statement; if a condition is <+!>TRUE<-!>, execute a single statement and check again. A block
<+!>WHILE<-!> loop can be one or more statements. The start of a block
<+!>WHILE<-!> loop is differentiated from a logical <+!>WHILE<-!></`>loop by the
<+!>DO<-!> keyword immediately after the condition. At some point in the loop some action must be taken that will make the condition
<+!>FALSE<-!>. If the condition never changes from <+!>TRUE<-!> to
<+!>FALSE<-!> you have what is known as an infinite loop; your computer will appear to be hung, even though it is rapidly executing things just as fast as it can. Be sure to thoroughly test all programs, but especially programs with loops!
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#2380,9360>INTEGER i<**>LET i = 0<+!><**>WHILE (i << 10)<-!> GOSUB sub<**>END<**>:sub<**>PRINTLN "i is ",i<**>INC i<**>RETURN<**><**>INTEGER i<**>LET i = 0<**><+!>WHILE (i << 10) DO<-!><**> PRINTLN "i is ",i<**> INC i<:f,QCourier,><+!><**>ENDWHILE<-!><:f>
<:#245,9360>Set the word wrap flag in an <+!>INPUTSTR<-!> or <+!>PROMPTSTR<-!> statement.
@Small_Header@<:#259,9360>Value
<:#240,9360>512 = 1000000000b = 1000o = 200h
@Small_Header@<:#259,9360>Remarks
<:#1455,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to word wrap from one input statement to the next input statement. If you reach the end of the input field PCBoard will automatically save the last word from the input field in an inter
nal buffer. The next input statement will use that saved word if both statements used the
<+!>WORDWRAP<-!> constant. If the passed variable isn't empty or if an input statement is used that doesn't have the
<+!>WORDWRAP<-!> flag set then the saved word will not be used.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#1590,9360>STRING s(5)<**>INTEGER i<**>CLS<**>FOR i = 1 TO 5<**> INPUTSTR "Line "+STRING(i),s(i),@X0E,40,MASK_ASCII(),<+!>WORDWRAP<-!>+NEWLINE<**>NEXT<**>CLS<**>FOR i = 1 TO 5<**> PRINTLN "Line ",i,": ",s(i)<**>NEXT
@Indent_List@<:#240,9360> <:f,QCourier,>node<:f> An integer expression with the node to update.
@Indent_List@<:#240,9360> <:f,QCourier,>stat<:f> A string expression with the new node status.
@Indent_List@<:#240,9360> <:f,QCourier,>name<:f> A string expression with the new node user name.
@Indent_List@<:#240,9360> <:f,QCourier,>city<:f> A string expression with the new node city.
@Indent_List@<:#240,9360> <:f,QCourier,>oper<:f> A string expression with the new node operation text.
@Indent_List@<:#240,9360> <:f,QCourier,>br<:f> A string expression with the new node broadcast text.
@Small_Header@<:#259,9360>Remarks
<:#1200,9360>To facilitate internode communications, a file named USERNET.XXX is maintained with an entry for each node on the system. This file is used by the BROADCAST command of PCBoard and to prevent multiple simultaneous logins, among other things. This statement
may be used to change information for the current node (for example, to update operation text during PPE execution) or other nodes (for example, to broadcast a message).
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#632,9360>RDUNET PCBNODE()<+!><**>WRUNET PCBNODE(),UN_STAT(),UN_NAME(),UN_CITY(),"Running "+PPENAME(),""<-!><**>RDUNET 1<**><+!>WRUNET 1,UN_STAT(),UN_NAME(),UN_CITY(),UN_OPER(),"Hello there node 1"<-!>
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Remarks
<:#1450,9360>Some DOOR applications require a USERS.SYS file to access information about the caller. This statement allows you to create that file prior to running an application via the
<+!>SHELL<-!> statement. Should the DOOR make changes to the USERS.SYS file, you should use the
<+!>RDUSYS<-!> statement after the <+!>SHELL<-!> to read the changes back into memory. It should be noted that it is not possible to create the USERS.SYS file with a TPA record with this statement.
<:#240,9360>Calculate the bitwise XOR (exclusive or) of two integer arguments.
@Small_Header@<:#259,9360>Syntax
<:#202,9360><:f,QCourier,>AND(iexp1,iexp2)<:f>
@Indent_List@<:#240,9360> <:f,QCourier,>iexp1<:f> Any integer expression.
@Indent_List@<:#240,9360> <:f,QCourier,>iexp2<:f> Any integer expression.
@Small_Header@<+@><:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>INTEGER<-!> Returns the bitwise XOR of iexp1 and iexp2.
@Small_Header@<:#259,9360>Remarks
<:#480,9360>This function may be used to toggle selected bits in an integer expression by XORing the expression with a mask that has the bits to toggle set to 1 and the bits to ignore set to 0.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#810,9360>' Toggle the bits in the low byte<**>PRINTLN <+!>XOR(1248h,00FFh)<-!><**>' Toggle a flag<**>INTEGER flag<**>LET flag =
@Indent_List@<:#240,9360> No arguments are required
@Small_Header@<:#259,9360>Return Type & Value
@Indent_List@<:#245,9360><+!>STRING<-!> Returns the yes character for the current language.
@Small_Header@<:#259,9360>Remarks
<:#720,9360>Support for foreign language yes/no responses can be easily added by using this function to determine what an affirmative response should be instead of hardcoding the english "Y" character.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>STRING ans<**>LET ans = <+!>YESCHAR()<-!><**>INPUTSTR "Run program now",ans,@X0E,1,"",AUTO+YESNO<**>IF (ans = NOCHAR()) END
<:#1445,9360>The <+!>INPUTSTR<-!> and <+!>PROMPTSTR<-!> statements have the ability to allow a yes/no response to be entered in addition to any valid characters passed to the statement. The extra characters allowed are Y/N (or whatever characters were defined for the c
urrent language; spanish would use S/N, french would use O/N, etc). Note that you do not need to pass any valid characters to use this flag; regardless of the other legal characters the international Y/N characters will be allowed.
@Small_Header@<:#259,9360>Examples
@Example_Text@<:#642,9360>STRING ans<**>LET ans = NOCHAR()<**>INPUTSTR "Run program now",ans,@X0E,1,"",AUTO+<+!>YESNO<-!><**>IF (ans = NOCHAR()) END